├── .gitignore
├── .php_cs
├── .travis.yml
├── LICENSE
├── README.md
├── composer.json
├── phpunit.xml
├── src
├── Application.php
├── Attendance
│ ├── Client.php
│ └── ServiceProvider.php
├── Auth
│ ├── HasStateParameter.php
│ ├── InvalidStateException.php
│ ├── OAuthClient.php
│ ├── ServiceProvider.php
│ └── SsoClient.php
├── Blackboard
│ ├── Client.php
│ └── ServiceProvider.php
├── Calendar
│ ├── Client.php
│ └── ServiceProvider.php
├── Callback
│ ├── Client.php
│ └── ServiceProvider.php
├── Chat
│ ├── Client.php
│ └── ServiceProvider.php
├── Checkin
│ ├── Client.php
│ └── ServiceProvider.php
├── Contact
│ ├── Client.php
│ └── ServiceProvider.php
├── Conversation
│ ├── Client.php
│ └── ServiceProvider.php
├── Department
│ ├── Client.php
│ └── ServiceProvider.php
├── H5app
│ ├── Client.php
│ └── ServiceProvider.php
├── Health
│ ├── Client.php
│ └── ServiceProvider.php
├── Kernel
│ ├── AccessToken.php
│ ├── BaseClient.php
│ ├── Concerns
│ │ └── InteractsWithCache.php
│ ├── Encryption
│ │ └── Encryptor.php
│ ├── Exceptions
│ │ ├── Exception.php
│ │ ├── InvalidArgumentException.php
│ │ ├── InvalidCredentialsException.php
│ │ └── RuntimeException.php
│ ├── Http
│ │ └── Client.php
│ ├── Providers
│ │ ├── AccessTokenServiceProvider.php
│ │ ├── ClientServiceProvider.php
│ │ ├── EncryptionServiceProvider.php
│ │ ├── LoggerServiceProvider.php
│ │ ├── RequestServiceProvider.php
│ │ └── ServerServiceProvider.php
│ └── Server.php
├── Media
│ ├── Client.php
│ └── ServiceProvider.php
├── Messages
│ ├── File.php
│ ├── Image.php
│ ├── Link.php
│ ├── Message.php
│ ├── Text.php
│ └── Voice.php
├── Microapp
│ ├── Client.php
│ └── ServiceProvider.php
├── Process
│ ├── Client.php
│ └── ServiceProvider.php
├── Report
│ ├── Client.php
│ └── ServiceProvider.php
├── Robot.php
├── Role
│ ├── Client.php
│ └── ServiceProvider.php
├── Schedule
│ ├── Client.php
│ └── ServiceProvider.php
├── User
│ ├── Client.php
│ └── ServiceProvider.php
└── helpers.php
└── tests
├── ApplicationTest.php
├── Blackboard
└── ClientTest.php
├── Calendar
└── ClientTest.php
├── Callback
└── ClientTest.php
├── Chat
└── ClientTest.php
├── Contact
└── ClientTest.php
├── Conversation
└── ClientTest.php
├── Department
└── ClientTest.php
├── Health
└── ClientTest.php
├── Kernel
├── Concerns
│ └── InteractsWithCacheTest.php
└── Encryption
│ └── EncryptorTest.php
├── Media
├── ClientTest.php
└── __fixtures__
│ └── foo.stub
├── Messages
├── FileTest.php
├── ImageTest.php
├── LinkTest.php
├── TextTest.php
└── VoiceTest.php
├── Microapp
└── ClientTest.php
├── Report
└── ClientTest.php
├── Role
└── ClientTest.php
├── Schedule
└── ClientTest.php
├── TestCase.php
├── TestResponse.php
└── User
└── ClientTest.php
/.gitignore:
--------------------------------------------------------------------------------
1 | /vendor/
2 | composer.lock
3 | .idea/
--------------------------------------------------------------------------------
/.php_cs:
--------------------------------------------------------------------------------
1 |
7 |
8 | This source file is subject to the MIT license that is bundled
9 | with this source code in the file LICENSE.
10 | EOF;
11 |
12 | return PhpCsFixer\Config::create()
13 | ->setRules([
14 | '@Symfony' => true,
15 | 'phpdoc_summary' => false,
16 | 'header_comment' => ['header' => $header],
17 | 'ordered_imports' => true,
18 | 'phpdoc_no_empty_return' => false,
19 | 'no_empty_comment' => false,
20 | ])
21 | ->setFinder(
22 | PhpCsFixer\Finder::create()
23 | ->exclude('vendor')
24 | ->in(__DIR__)
25 | )
26 | ->setUsingCache(false)
27 | ;
28 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | env:
4 | global:
5 | - setup=stable
6 |
7 | matrix:
8 | fast_finish: true
9 | include:
10 | - php: 7.0
11 | - php: 7.0
12 | env: setup=lowest
13 | - php: 7.1
14 | - php: 7.1
15 | env: setup=lowest
16 | - php: 7.2
17 | - php: 7.2
18 | env: setup=lowest
19 | - php: 7.3
20 | - php: 7.3
21 | env: setup=lowest
22 |
23 | install:
24 | - if [[ $setup = 'stable' ]]; then travis_retry composer update --prefer-dist --no-interaction --prefer-stable --no-suggest; fi
25 | - if [[ $setup = 'lowest' ]]; then travis_retry composer update --prefer-dist --no-interaction --prefer-lowest --prefer-stable --no-suggest; fi
26 |
27 | script: ./vendor/bin/phpunit
28 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 张铭阳
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
EasyDingTalk
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | ## 介绍
14 |
15 | EasyDingTalk 封装了钉钉身份验证、通讯录管理、消息通知、审批、群机器人、业务事件回调管理等服务端接口,让开发者可以使用简单的配置,提供简洁的 API 以供方便快速地调用钉钉接口。
16 |
17 | ## 环境要求
18 |
19 | - PHP 7.0+
20 | - [Composer](https://getcomposer.org/)
21 |
22 | ## 安装
23 |
24 | ```bash
25 | composer require mingyoung/dingtalk:^2.0
26 | ```
27 |
28 | ## 使用
29 |
30 | ```php
31 | use EasyDingTalk\Application;
32 |
33 | $config = [
34 | 'corp_id' => 'dingd3ir8195906jfo93',
35 |
36 | 'app_key' => 'dingwu33fo1fjc0fszad',
37 | 'app_secret' => 'RsuMFgEIY3jg5UMidkvwpzEobWjf9Fcu3oLqLyCUIgzULm54WcV7j9fi3fJlUshk',
38 | ];
39 |
40 | $app = new Application($config);
41 | ```
42 |
43 | ## 文档
44 |
45 | [https://docs.easydingtalk.org](https://docs.easydingtalk.org)
46 |
47 |
48 | ## License
49 |
50 | MIT
51 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mingyoung/dingtalk",
3 | "description": "EasyDingTalk, Alibaba Dingtalk SDK for PHP",
4 | "keywords": [
5 | "dingtalk",
6 | "dingding",
7 | "easydingtalk",
8 | "sdk",
9 | "钉钉"
10 |
11 | ],
12 | "license": "MIT",
13 | "authors": [
14 | {
15 | "name": "张铭阳",
16 | "email": "mingyoungcheung@gmail.com"
17 | }
18 | ],
19 | "require": {
20 | "php": ">=7.0",
21 | "overtrue/http": "1.1.3",
22 | "pimple/pimple": "^3.0",
23 | "psr/simple-cache": "^1.0",
24 | "monolog/monolog": "^1.23 || ^2.0",
25 | "symfony/cache": "^3.3 || ^4.0 || ^5.0",
26 | "symfony/http-foundation": "^3.2 || ^4.0 || ^5.0"
27 | },
28 | "require-dev": {
29 | "mockery/mockery": "^1.0",
30 | "phpunit/phpunit": "^6.5 || ^7.0"
31 | },
32 | "autoload": {
33 | "psr-4": {
34 | "EasyDingTalk\\": "src/"
35 | },
36 | "files": [
37 | "src/helpers.php"
38 | ]
39 | },
40 | "autoload-dev": {
41 | "psr-4": {
42 | "EasyDingTalk\\Tests\\": "tests/"
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 | tests
14 |
15 |
16 |
17 |
18 |
19 | src
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/Application.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk;
13 |
14 | use Overtrue\Http\Support\Collection;
15 | use Pimple\Container;
16 |
17 | /**
18 | * @property \EasyDingTalk\Auth\SsoClient $sso
19 | * @property \EasyDingTalk\Auth\OAuthClient $oauth
20 | * @property \EasyDingTalk\Chat\Client $chat
21 | * @property \EasyDingTalk\Role\Client $role
22 | * @property \EasyDingTalk\User\Client $user
23 | * @property \EasyDingTalk\Media\Client $media
24 | * @property \EasyDingTalk\H5app\Client $h5app
25 | * @property \EasyDingTalk\Health\Client $health
26 | * @property \EasyDingTalk\Report\Client $report
27 | * @property \EasyDingTalk\Checkin\Client $checkin
28 | * @property \EasyDingTalk\Contact\Client $contact
29 | * @property \EasyDingTalk\Process\Client $process
30 | * @property \EasyDingTalk\Calendar\Client $calendar
31 | * @property \EasyDingTalk\Callback\Client $callback
32 | * @property \EasyDingTalk\Microapp\Client $microapp
33 | * @property \EasyDingTalk\Schedule\Client $schedule
34 | * @property \EasyDingTalk\Blackboard\Client $blackboard
35 | * @property \EasyDingTalk\Attendance\Client $attendance
36 | * @property \EasyDingTalk\Department\Client $department
37 | * @property \EasyDingTalk\Conversation\Client $conversation
38 | * @property \EasyDingTalk\Kernel\Http\Client $client
39 | * @property \Monolog\Logger $logger
40 | * @property \EasyDingTalk\Kernel\Server $server
41 | * @property \Symfony\Component\HttpFoundation\Request $request
42 | * @property \EasyDingTalk\Kernel\Encryption\Encryptor $encryptor
43 | * @property \EasyDingTalk\Kernel\AccessToken $access_token
44 | */
45 | class Application extends Container
46 | {
47 | /**
48 | * @var array
49 | */
50 | protected $providers = [
51 | Auth\ServiceProvider::class,
52 | Chat\ServiceProvider::class,
53 | Role\ServiceProvider::class,
54 | User\ServiceProvider::class,
55 | Media\ServiceProvider::class,
56 | H5app\ServiceProvider::class,
57 | Health\ServiceProvider::class,
58 | Report\ServiceProvider::class,
59 | Checkin\ServiceProvider::class,
60 | Contact\ServiceProvider::class,
61 | Process\ServiceProvider::class,
62 | Calendar\ServiceProvider::class,
63 | Callback\ServiceProvider::class,
64 | Microapp\ServiceProvider::class,
65 | Schedule\ServiceProvider::class,
66 | Blackboard\ServiceProvider::class,
67 | Attendance\ServiceProvider::class,
68 | Department\ServiceProvider::class,
69 | Conversation\ServiceProvider::class,
70 | Kernel\Providers\ClientServiceProvider::class,
71 | Kernel\Providers\LoggerServiceProvider::class,
72 | Kernel\Providers\ServerServiceProvider::class,
73 | Kernel\Providers\RequestServiceProvider::class,
74 | Kernel\Providers\EncryptionServiceProvider::class,
75 | Kernel\Providers\AccessTokenServiceProvider::class,
76 | ];
77 |
78 | /**
79 | * Application constructor.
80 | *
81 | * @param array $config
82 | * @param array $values
83 | */
84 | public function __construct($config = [], array $values = [])
85 | {
86 | parent::__construct($values);
87 |
88 | $this['config'] = function () use ($config) {
89 | return new Collection($config);
90 | };
91 |
92 | foreach ($this->providers as $provider) {
93 | $this->register(new $provider());
94 | }
95 | }
96 |
97 | /**
98 | * @param $name
99 | *
100 | * @return mixed
101 | */
102 | public function __get($name)
103 | {
104 | return $this[$name];
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/src/Attendance/Client.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Attendance;
13 |
14 | use EasyDingTalk\Kernel\BaseClient;
15 |
16 | class Client extends BaseClient
17 | {
18 | /**
19 | * 企业考勤排班详情
20 | *
21 | * @param string $date
22 | * @param int|null $offset
23 | * @param int|null $size
24 | *
25 | * @return mixed
26 | */
27 | public function schedules($date, $offset = null, $size = null)
28 | {
29 | return $this->client->postJson('topapi/attendance/listschedule', [
30 | 'workDate' => $date, 'offset' => $offset, 'size' => $size,
31 | ]);
32 | }
33 |
34 | /**
35 | * 企业考勤组详情
36 | *
37 | * @param int|null $offset
38 | * @param int|null $size
39 | *
40 | * @return mixed
41 | */
42 | public function groups($offset = null, $size = null)
43 | {
44 | return $this->client->postJson('topapi/attendance/getsimplegroups', compact('offset', 'size'));
45 | }
46 |
47 | /**
48 | * 获取用户考勤组
49 | *
50 | * @param string $userId
51 | *
52 | * @return mixed
53 | */
54 | public function userGroup($userId)
55 | {
56 | return $this->client->postJson('topapi/attendance/getusergroup', ['userid' => $userId]);
57 | }
58 |
59 | /**
60 | * 获取打卡详情
61 | *
62 | * @param array $params
63 | *
64 | * @return mixed
65 | */
66 | public function records($params)
67 | {
68 | return $this->client->postJson('attendance/listRecord', $params);
69 | }
70 |
71 | /**
72 | * 获取打卡结果
73 | *
74 | * @param array $params
75 | *
76 | * @return mixed
77 | */
78 | public function results($params)
79 | {
80 | return $this->client->postJson('attendance/list', $params);
81 | }
82 |
83 | /**
84 | * 获取请假时长
85 | *
86 | * @param string $userId
87 | * @param string $from
88 | * @param string $to
89 | *
90 | * @return mixed
91 | */
92 | public function duration($userId, $from, $to)
93 | {
94 | return $this->client->postJson('topapi/attendance/getleaveapproveduration', [
95 | 'userid' => $userId, 'from_date' => $from, 'to_date' => $to,
96 | ]);
97 | }
98 |
99 | /**
100 | * 查询请假状态
101 | *
102 | * @param array $params
103 | *
104 | * @return mixed
105 | */
106 | public function status($params)
107 | {
108 | return $this->client->postJson('topapi/attendance/getleavestatus', $params);
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/src/Attendance/ServiceProvider.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Attendance;
13 |
14 | use Pimple\Container;
15 | use Pimple\ServiceProviderInterface;
16 |
17 | class ServiceProvider implements ServiceProviderInterface
18 | {
19 | /**
20 | * Registers services on the given container.
21 | * This method should only be used to configure services and parameters.
22 | * It should not get services.
23 | *
24 | * @param \Pimple\Container $pimple A container instance
25 | */
26 | public function register(Container $pimple)
27 | {
28 | $pimple['attendance'] = function ($app) {
29 | return new Client($app);
30 | };
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/Auth/HasStateParameter.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Auth;
13 |
14 | use function EasyDingTalk\str_random;
15 | use function EasyDingTalk\tap;
16 |
17 | trait HasStateParameter
18 | {
19 | /**
20 | * @var bool
21 | */
22 | protected $stateless = false;
23 |
24 | /**
25 | * @return $this
26 | */
27 | public function stateless()
28 | {
29 | $this->stateless = true;
30 |
31 | return $this;
32 | }
33 |
34 | /**
35 | * Generate state.
36 | *
37 | * @return string
38 | */
39 | protected function makeState()
40 | {
41 | return tap(str_random(64), function ($state) {
42 | $this->app['request']->getSession()->set('state', $state);
43 | });
44 | }
45 |
46 | /**
47 | * @param string|null $state
48 | *
49 | * @return bool
50 | */
51 | protected function hasValidState($state)
52 | {
53 | if ($this->stateless) {
54 | return true;
55 | }
56 |
57 | return !is_null($state) && ($state === $this->app['request']->getSession()->get('state'));
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/Auth/InvalidStateException.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Auth;
13 |
14 | use EasyDingTalk\Kernel\Exceptions\Exception;
15 |
16 | class InvalidStateException extends Exception
17 | {
18 | //
19 | }
20 |
--------------------------------------------------------------------------------
/src/Auth/OAuthClient.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Auth;
13 |
14 | use EasyDingTalk\Kernel\Http\Client;
15 | use Symfony\Component\HttpFoundation\RedirectResponse;
16 |
17 | class OAuthClient extends Client
18 | {
19 | use HasStateParameter;
20 |
21 | /**
22 | * @var array
23 | */
24 | protected $credential;
25 |
26 | /**
27 | * @var bool
28 | */
29 | protected $withQrConnect = false;
30 |
31 | /**
32 | * @var string|null
33 | */
34 | protected $redirect;
35 |
36 | /**
37 | * @param string $name
38 | *
39 | * @return $this
40 | */
41 | public function use($name)
42 | {
43 | $this->credential = $this->app['config']->get('oauth')[$name];
44 |
45 | return $this;
46 | }
47 |
48 | /**
49 | * @return string
50 | */
51 | public function getRedirectUrl()
52 | {
53 | return $this->redirect ?: $this->credential['redirect'];
54 | }
55 |
56 | /**
57 | * @param string $url
58 | *
59 | * @return $this
60 | */
61 | public function setRedirectUrl($url)
62 | {
63 | $this->redirect = $url;
64 |
65 | return $this;
66 | }
67 |
68 | /**
69 | * @return $this
70 | */
71 | public function withQrConnect()
72 | {
73 | $this->withQrConnect = true;
74 |
75 | return $this;
76 | }
77 |
78 | /**
79 | * Redirect to the authentication page.
80 | *
81 | * @param string|null $url
82 | *
83 | * @return \Symfony\Component\HttpFoundation\RedirectResponse
84 | */
85 | public function redirect($url = null)
86 | {
87 | $query = [
88 | 'appid' => $this->credential['client_id'],
89 | 'response_type' => 'code',
90 | 'scope' => $this->credential['scope'],
91 | 'state' => $this->makeState(),
92 | 'redirect_uri' => $url ?: $this->getRedirectUrl(),
93 | ];
94 |
95 | return new RedirectResponse(
96 | sprintf('https://oapi.dingtalk.com/connect/%s?%s', $this->withQrConnect ? 'qrconnect' : 'oauth2/sns_authorize', http_build_query(array_filter($query)))
97 | );
98 | }
99 |
100 | /**
101 | * @return array
102 | *
103 | * @throws \EasyDingTalk\Auth\InvalidStateException
104 | */
105 | public function user()
106 | {
107 | if (!$this->hasValidState($this->app['request']->get('state'))) {
108 | throw new InvalidStateException();
109 | }
110 |
111 | $data = [
112 | 'tmp_auth_code' => $this->app['request']->get('code'),
113 | ];
114 |
115 | $query = [
116 | 'accessKey' => $this->credential['client_id'],
117 | 'timestamp' => $timestamp = (int) microtime(true) * 1000,
118 | 'signature' => $this->signature($timestamp),
119 | ];
120 |
121 | return $this->postJson('sns/getuserinfo_bycode', $data, $query);
122 | }
123 |
124 | /**
125 | * 计算签名
126 | *
127 | * @param int $timestamp
128 | *
129 | * @return string
130 | */
131 | public function signature($timestamp)
132 | {
133 | return base64_encode(hash_hmac('sha256', $timestamp, $this->credential['client_secret'], true));
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/src/Auth/ServiceProvider.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Auth;
13 |
14 | use Pimple\Container;
15 | use Pimple\ServiceProviderInterface;
16 | use Symfony\Component\HttpFoundation\Session\Session;
17 |
18 | class ServiceProvider implements ServiceProviderInterface
19 | {
20 | /**
21 | * Registers services on the given container.
22 | * This method should only be used to configure services and parameters.
23 | * It should not get services.
24 | *
25 | * @param \Pimple\Container $pimple A container instance
26 | */
27 | public function register(Container $pimple)
28 | {
29 | $pimple['sso'] = function ($app) {
30 | return new SsoClient($app);
31 | };
32 |
33 | $pimple['oauth'] = function ($app) {
34 | if (!$app['request']->hasSession()) {
35 | $app['request']->setSession(new Session());
36 | }
37 |
38 | return new OAuthClient($app);
39 | };
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/Auth/SsoClient.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Auth;
13 |
14 | use EasyDingTalk\Kernel\Http\Client;
15 |
16 | class SsoClient extends Client
17 | {
18 | /**
19 | * 获取应用后台免登 AccessToken
20 | *
21 | * @return mixed
22 | */
23 | public function getToken()
24 | {
25 | return $this->get('sso/gettoken', [
26 | 'corpid' => $this->app['config']->get('corp_id'),
27 | 'corpsecret' => $this->app['config']->get('sso_secret'),
28 | ]);
29 | }
30 |
31 | /**
32 | * 获取用户身份信息
33 | *
34 | * @return mixed
35 | */
36 | public function user()
37 | {
38 | return $this->get('sso/getuserinfo', [
39 | 'access_token' => $this->getToken()['access_token'],
40 | 'code' => $this->app['request']->get('code'),
41 | ]);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/Blackboard/Client.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Blackboard;
13 |
14 | use EasyDingTalk\Kernel\BaseClient;
15 |
16 | class Client extends BaseClient
17 | {
18 | /**
19 | * 获取用户公告数据
20 | *
21 | * @param string $userid
22 | *
23 | * @return mixed
24 | */
25 | public function list($userid)
26 | {
27 | return $this->client->postJson('topapi/blackboard/listtopten', compact('userid'));
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/Blackboard/ServiceProvider.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Blackboard;
13 |
14 | use Pimple\Container;
15 | use Pimple\ServiceProviderInterface;
16 |
17 | class ServiceProvider implements ServiceProviderInterface
18 | {
19 | /**
20 | * Registers services on the given container.
21 | * This method should only be used to configure services and parameters.
22 | * It should not get services.
23 | *
24 | * @param \Pimple\Container $pimple A container instance
25 | */
26 | public function register(Container $pimple)
27 | {
28 | $pimple['blackboard'] = function ($app) {
29 | return new Client($app);
30 | };
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/Calendar/Client.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Calendar;
13 |
14 | use EasyDingTalk\Kernel\BaseClient;
15 |
16 | class Client extends BaseClient
17 | {
18 | /**
19 | * 创建日程
20 | *
21 | * @param array $params
22 | *
23 | * @return mixed
24 | */
25 | public function create($params)
26 | {
27 | return $this->client->postJson('topapi/calendar/create', $params);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/Calendar/ServiceProvider.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Calendar;
13 |
14 | use Pimple\Container;
15 | use Pimple\ServiceProviderInterface;
16 |
17 | class ServiceProvider implements ServiceProviderInterface
18 | {
19 | /**
20 | * Registers services on the given container.
21 | * This method should only be used to configure services and parameters.
22 | * It should not get services.
23 | *
24 | * @param \Pimple\Container $pimple A container instance
25 | */
26 | public function register(Container $pimple)
27 | {
28 | $pimple['calendar'] = function ($app) {
29 | return new Client($app);
30 | };
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/Callback/Client.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Callback;
13 |
14 | use EasyDingTalk\Kernel\BaseClient;
15 |
16 | class Client extends BaseClient
17 | {
18 | /**
19 | * 注册业务事件回调接口
20 | *
21 | * @param array $params
22 | *
23 | * @return mixed
24 | */
25 | public function register($params)
26 | {
27 | $params['token'] = $this->app['config']->get('token');
28 | $params['aes_key'] = $this->app['config']->get('aes_key');
29 |
30 | return $this->client->postJson('call_back/register_call_back', $params);
31 | }
32 |
33 | /**
34 | * 查询事件回调接口
35 | *
36 | * @return mixed
37 | */
38 | public function list()
39 | {
40 | return $this->client->get('call_back/get_call_back');
41 | }
42 |
43 | /**
44 | * 更新事件回调接口
45 | *
46 | * @return mixed
47 | */
48 | public function update($params)
49 | {
50 | $params['token'] = $this->app['config']->get('token');
51 | $params['aes_key'] = $this->app['config']->get('aes_key');
52 |
53 | return $this->client->postJson('call_back/update_call_back', $params);
54 | }
55 |
56 | /**
57 | * 删除事件回调接口
58 | *
59 | * @return mixed
60 | */
61 | public function delete()
62 | {
63 | return $this->client->get('call_back/delete_call_back');
64 | }
65 |
66 | /**
67 | * 获取回调失败结果
68 | *
69 | * @return mixed
70 | */
71 | public function failed()
72 | {
73 | return $this->client->get('call_back/get_call_back_failed_result');
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/Callback/ServiceProvider.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Callback;
13 |
14 | use Pimple\Container;
15 | use Pimple\ServiceProviderInterface;
16 |
17 | class ServiceProvider implements ServiceProviderInterface
18 | {
19 | /**
20 | * Registers services on the given container.
21 | * This method should only be used to configure services and parameters.
22 | * It should not get services.
23 | *
24 | * @param \Pimple\Container $pimple A container instance
25 | */
26 | public function register(Container $pimple)
27 | {
28 | $pimple['callback'] = function ($app) {
29 | return new Client($app);
30 | };
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/Chat/Client.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Chat;
13 |
14 | use EasyDingTalk\Kernel\BaseClient;
15 |
16 | class Client extends BaseClient
17 | {
18 | /**
19 | * 发送群消息
20 | *
21 | * @param string $chatId
22 | * @param string $message
23 | *
24 | * @return mixed
25 | */
26 | public function send($chatId, $message)
27 | {
28 | return $this->client->postJson('chat/send', [
29 | 'chatid' => $chatId, 'msg' => $message,
30 | ]);
31 | }
32 |
33 | /**
34 | * 查询群消息已读人员列表
35 | *
36 | * @param string $messageId
37 | * @param int $cursor
38 | * @param int $size
39 | *
40 | * @return mixed
41 | */
42 | public function result($messageId, $cursor, $size)
43 | {
44 | return $this->client->get('chat/getReadList', [
45 | 'messageId' => $messageId, 'cursor' => $cursor, 'size' => $size,
46 | ]);
47 | }
48 |
49 | /**
50 | * 创建会话
51 | *
52 | * @param array $params
53 | *
54 | * @return mixed
55 | */
56 | public function create($params)
57 | {
58 | return $this->client->postJson('chat/create', $params);
59 | }
60 |
61 | /**
62 | * 修改会话
63 | *
64 | * @param string $chatId
65 | * @param array $params
66 | *
67 | * @return mixed
68 | */
69 | public function update($chatId, $params)
70 | {
71 | return $this->client->postJson('chat/update', ['chatid' => $chatId] + $params);
72 | }
73 |
74 | /**
75 | * 获取会话
76 | *
77 | * @param string $chatId
78 | *
79 | * @return mixed
80 | */
81 | public function get($chatId)
82 | {
83 | return $this->client->get('chat/get', ['chatid' => $chatId]);
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/Chat/ServiceProvider.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Chat;
13 |
14 | use Pimple\Container;
15 | use Pimple\ServiceProviderInterface;
16 |
17 | class ServiceProvider implements ServiceProviderInterface
18 | {
19 | /**
20 | * Registers services on the given container.
21 | * This method should only be used to configure services and parameters.
22 | * It should not get services.
23 | *
24 | * @param \Pimple\Container $pimple A container instance
25 | */
26 | public function register(Container $pimple)
27 | {
28 | $pimple['chat'] = function ($app) {
29 | return new Client($app);
30 | };
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/Checkin/Client.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Checkin;
13 |
14 | use EasyDingTalk\Kernel\BaseClient;
15 |
16 | class Client extends BaseClient
17 | {
18 | /**
19 | * 获取部门用户签到记录
20 | *
21 | * @param array $params
22 | *
23 | * @return mixed
24 | */
25 | public function records($params)
26 | {
27 | return $this->client->get('checkin/record', $params);
28 | }
29 |
30 | /**
31 | * 获取用户签到记录
32 | *
33 | * @param array $params
34 | *
35 | * @return mixed
36 | */
37 | public function get($params)
38 | {
39 | return $this->client->postJson('topapi/checkin/record/get', $params);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/Checkin/ServiceProvider.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Checkin;
13 |
14 | use Pimple\Container;
15 | use Pimple\ServiceProviderInterface;
16 |
17 | class ServiceProvider implements ServiceProviderInterface
18 | {
19 | /**
20 | * Registers services on the given container.
21 | * This method should only be used to configure services and parameters.
22 | * It should not get services.
23 | *
24 | * @param \Pimple\Container $pimple A container instance
25 | */
26 | public function register(Container $pimple)
27 | {
28 | $pimple['checkin'] = function ($app) {
29 | return new Client($app);
30 | };
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/Contact/Client.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Contact;
13 |
14 | use EasyDingTalk\Kernel\BaseClient;
15 |
16 | class Client extends BaseClient
17 | {
18 | /**
19 | * 获取外部联系人标签列表
20 | *
21 | * @param int $offset
22 | * @param int $size
23 | *
24 | * @return mixed
25 | */
26 | public function labels($offset = 0, $size = 100)
27 | {
28 | return $this->client->postJson('topapi/extcontact/listlabelgroups', compact('offset', 'size'));
29 | }
30 |
31 | /**
32 | * 获取外部联系人列表
33 | *
34 | * @param int $offset
35 | * @param int $size
36 | *
37 | * @return mixed
38 | */
39 | public function list($offset = 0, $size = 100)
40 | {
41 | return $this->client->postJson('topapi/extcontact/list', compact('offset', 'size'));
42 | }
43 |
44 | /**
45 | * 获取企业外部联系人详情
46 | *
47 | * @param string $userId
48 | *
49 | * @return mixed
50 | */
51 | public function get($userId)
52 | {
53 | return $this->client->postJson('topapi/extcontact/get', ['user_id' => $userId]);
54 | }
55 |
56 | /**
57 | * 添加外部联系人
58 | *
59 | * @param array $contact
60 | *
61 | * @return mixed
62 | */
63 | public function create($contact)
64 | {
65 | return $this->client->postJson('topapi/extcontact/create', compact('contact'));
66 | }
67 |
68 | /**
69 | * 更新外部联系人
70 | *
71 | * @param string $userId
72 | * @param array $contact
73 | *
74 | * @return mixed
75 | */
76 | public function update($userId, $contact)
77 | {
78 | $contact = ['user_id' => $userId] + $contact;
79 |
80 | return $this->client->postJson('topapi/extcontact/update', compact('contact'));
81 | }
82 |
83 | /**
84 | * 删除外部联系人
85 | *
86 | * @param string $userId
87 | *
88 | * @return mixed
89 | */
90 | public function delete($userId)
91 | {
92 | return $this->client->postJson('topapi/extcontact/delete', ['user_id' => $userId]);
93 | }
94 |
95 | /**
96 | * 获取通讯录权限范围
97 | *
98 | * @return mixed
99 | */
100 | public function scopes()
101 | {
102 | return $this->client->get('auth/scopes');
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/src/Contact/ServiceProvider.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Contact;
13 |
14 | use Pimple\Container;
15 | use Pimple\ServiceProviderInterface;
16 |
17 | class ServiceProvider implements ServiceProviderInterface
18 | {
19 | /**
20 | * Registers services on the given container.
21 | * This method should only be used to configure services and parameters.
22 | * It should not get services.
23 | *
24 | * @param \Pimple\Container $pimple A container instance
25 | */
26 | public function register(Container $pimple)
27 | {
28 | $pimple['contact'] = function ($app) {
29 | return new Client($app);
30 | };
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/Conversation/Client.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Conversation;
13 |
14 | use EasyDingTalk\Kernel\BaseClient;
15 | use function EasyDingTalk\tap;
16 |
17 | class Client extends BaseClient
18 | {
19 | /**
20 | * 发送普通消息
21 | *
22 | * @param string $sender
23 | * @param string $cid
24 | * @param array $message
25 | *
26 | * @return mixed
27 | */
28 | public function sendGeneralMessage($sender, $cid, $message)
29 | {
30 | return $this->client->postJson('message/send_to_conversation', [
31 | 'sender' => $sender, 'cid' => $cid, 'msg' => $message,
32 | ]);
33 | }
34 |
35 | /**
36 | * 发送工作通知消息
37 | *
38 | * @param array $params
39 | *
40 | * @return mixed
41 | */
42 | public function sendCorporationMessage($params)
43 | {
44 | return $this->client->post('topapi/message/corpconversation/asyncsend_v2', $params);
45 | }
46 |
47 | /**
48 | * @param int $taskId
49 | *
50 | * @return mixed
51 | */
52 | public function corporationMessage($taskId)
53 | {
54 | $client = new class($this->app) extends BaseClient {
55 | /**
56 | * 任务 ID
57 | *
58 | * @var int
59 | */
60 | protected $taskId;
61 |
62 | /**
63 | * @param int
64 | */
65 | public function setTaskId($taskId)
66 | {
67 | $this->taskId = $taskId;
68 |
69 | return $this;
70 | }
71 |
72 | /**
73 | * 查询工作通知消息的发送进度
74 | *
75 | * @return mixed
76 | */
77 | public function progress()
78 | {
79 | return $this->client->postJson('topapi/message/corpconversation/getsendprogress', [
80 | 'agent_id' => $this->app['config']['agent_id'], 'task_id' => $this->taskId,
81 | ]);
82 | }
83 |
84 | /**
85 | * 查询工作通知消息的发送结果
86 | *
87 | * @return mixed
88 | */
89 | public function result()
90 | {
91 | return $this->client->postJson('topapi/message/corpconversation/getsendresult', [
92 | 'agent_id' => $this->app['config']['agent_id'], 'task_id' => $this->taskId,
93 | ]);
94 | }
95 | };
96 |
97 | return tap($client, function ($client) use ($taskId) {
98 | $client->setTaskId($taskId);
99 | });
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/src/Conversation/ServiceProvider.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Conversation;
13 |
14 | use Pimple\Container;
15 | use Pimple\ServiceProviderInterface;
16 |
17 | class ServiceProvider implements ServiceProviderInterface
18 | {
19 | /**
20 | * Registers services on the given container.
21 | * This method should only be used to configure services and parameters.
22 | * It should not get services.
23 | *
24 | * @param \Pimple\Container $pimple A container instance
25 | */
26 | public function register(Container $pimple)
27 | {
28 | $pimple['conversation'] = function ($app) {
29 | return new Client($app);
30 | };
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/Department/Client.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Department;
13 |
14 | use EasyDingTalk\Kernel\BaseClient;
15 |
16 | class Client extends BaseClient
17 | {
18 | /**
19 | * 获取子部门 ID 列表
20 | *
21 | * @param string $id 部门ID
22 | *
23 | * @return mixed
24 | */
25 | public function getSubDepartmentIds($id)
26 | {
27 | return $this->client->get('department/list_ids', compact('id'));
28 | }
29 |
30 | /**
31 | * 获取部门列表
32 | *
33 | * @param bool $isFetchChild
34 | * @param string $id
35 | * @param string $lang
36 | *
37 | * @return mixed
38 | */
39 | public function list($id = null, bool $isFetchChild = false, $lang = null)
40 | {
41 | return $this->client->get('department/list', [
42 | 'id' => $id, 'lang' => $lang, 'fetch_child' => $isFetchChild ? 'true' : 'false',
43 | ]);
44 | }
45 |
46 | /**
47 | * 获取部门详情
48 | *
49 | * @param string $id
50 | * @param string $lang
51 | *
52 | * @return mixed
53 | */
54 | public function get($id, $lang = null)
55 | {
56 | return $this->client->get('department/get', compact('id', 'lang'));
57 | }
58 |
59 | /**
60 | * 查询部门的所有上级父部门路径
61 | *
62 | * @param string $id
63 | *
64 | * @return mixed
65 | */
66 | public function getParentsById($id)
67 | {
68 | return $this->client->get('department/list_parent_depts_by_dept', compact('id'));
69 | }
70 |
71 | /**
72 | * 查询指定用户的所有上级父部门路径
73 | *
74 | * @param string $userId
75 | *
76 | * @return mixed
77 | */
78 | public function getParentsByUserId($userId)
79 | {
80 | return $this->client->get('department/list_parent_depts', compact('userId'));
81 | }
82 |
83 | /**
84 | * 创建部门
85 | *
86 | * @param array $params
87 | *
88 | * @return mixed
89 | */
90 | public function create(array $params)
91 | {
92 | return $this->client->postJson('department/create', $params);
93 | }
94 |
95 | /**
96 | * 更新部门
97 | *
98 | * @param string $id
99 | * @param array $params
100 | *
101 | * @return mixed
102 | */
103 | public function update($id, array $params)
104 | {
105 | return $this->client->postJson('department/update', compact('id') + $params);
106 | }
107 |
108 | /**
109 | * 删除部门
110 | *
111 | * @param string $id
112 | *
113 | * @return mixed
114 | */
115 | public function delete($id)
116 | {
117 | return $this->client->get('department/delete', compact('id'));
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/src/Department/ServiceProvider.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Department;
13 |
14 | use Pimple\Container;
15 | use Pimple\ServiceProviderInterface;
16 |
17 | class ServiceProvider implements ServiceProviderInterface
18 | {
19 | /**
20 | * Registers services on the given container.
21 | * This method should only be used to configure services and parameters.
22 | * It should not get services.
23 | *
24 | * @param \Pimple\Container $pimple A container instance
25 | */
26 | public function register(Container $pimple)
27 | {
28 | $pimple['department'] = function ($app) {
29 | return new Client($app);
30 | };
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/H5app/Client.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\H5app;
13 |
14 | use EasyDingTalk\Kernel\BaseClient;
15 | use EasyDingTalk\Kernel\Concerns\InteractsWithCache;
16 | use EasyDingTalk\Kernel\Exceptions\InvalidCredentialsException;
17 |
18 | class Client extends BaseClient
19 | {
20 | use InteractsWithCache;
21 |
22 | /**
23 | * 获取 jsapi_ticket
24 | *
25 | * @return mixed
26 | */
27 | public function get()
28 | {
29 | if ($value = $this->getCache()->get($this->cacheFor())) {
30 | return $value;
31 | }
32 | $value = $this->client->get('get_jsapi_ticket');
33 | if (0 !== $value['errcode']) {
34 | throw new InvalidCredentialsException(json_encode($value));
35 | }
36 | $this->getCache()->set($this->cacheFor(), $value, $value['expires_in']);
37 | return $value;
38 | }
39 |
40 | /**
41 | * 获取 ticket
42 | *
43 | * @return string
44 | */
45 | public function getTicket()
46 | {
47 | return $this->get()['ticket'];
48 | }
49 |
50 | /**
51 | * 获取签名相关信息
52 | *
53 | * @param string $url
54 | *
55 | * @return mixed
56 | */
57 | public function getSignature($url)
58 | {
59 | $nonceStr = $this->getNonceStr();
60 | $timeStamp = time();
61 | $plain = 'jsapi_ticket=' . $this->getTicket() . '&noncestr=' . $nonceStr . '×tamp=' . $timeStamp . '&url=' . $url;
62 | $signature = sha1($plain);
63 | return [
64 | 'agentId' => $this->app['config']->get('agent_id'),
65 | 'corpId' => $this->app['config']->get('corp_id'),
66 | 'timeStamp' => $timeStamp,
67 | 'nonceStr' => $nonceStr,
68 | 'signature' => $signature,
69 | 'url' => $url
70 | ];
71 | }
72 |
73 | /**
74 | * 缓存 Key
75 | *
76 | * @return string
77 | */
78 | protected function cacheFor()
79 | {
80 | return sprintf('jsapi_ticket.%s', $this->app['config']->get('app_key'));
81 | }
82 |
83 | /**
84 | * 生产 随机字符串
85 | *
86 | * @return string
87 | */
88 | protected function getNonceStr($length=16)
89 | {
90 | $strs = "QWERTYUIOPASDFGHJKLZXCVBNM1234567890qwertyuiopasdfghjklzxcvbnm";
91 | return substr(str_shuffle($strs), mt_rand(0, strlen($strs)-11), $length);
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/src/H5app/ServiceProvider.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\H5app;
13 |
14 | use Pimple\Container;
15 | use Pimple\ServiceProviderInterface;
16 |
17 | class ServiceProvider implements ServiceProviderInterface
18 | {
19 | /**
20 | * Registers services on the given container.
21 | * This method should only be used to configure services and parameters.
22 | * It should not get services.
23 | *
24 | * @param \Pimple\Container $pimple A container instance
25 | */
26 | public function register(Container $pimple)
27 | {
28 | $pimple['h5app'] = function ($app) {
29 | return new Client($app);
30 | };
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/Health/Client.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Health;
13 |
14 | use EasyDingTalk\Kernel\BaseClient;
15 |
16 | class Client extends BaseClient
17 | {
18 | /**
19 | * 获取用户钉钉运动开启状态
20 | *
21 | * @param string $userId
22 | *
23 | * @return mixed
24 | */
25 | public function status($userId)
26 | {
27 | return $this->client->postJson('topapi/health/stepinfo/getuserstatus', ['userid' => $userId]);
28 | }
29 |
30 | /**
31 | * 获取个人钉钉运动数据
32 | *
33 | * @param string $id
34 | * @param string $dates
35 | *
36 | * @return mixed
37 | */
38 | public function byUser($id, $dates)
39 | {
40 | return $this->client->postJson('topapi/health/stepinfo/list', ['type' => 0, 'object_id' => $id, 'stat_dates' => $dates]);
41 | }
42 |
43 | /**
44 | * 获取部门钉钉运动数据
45 | *
46 | * @param string $id
47 | * @param string $dates
48 | *
49 | * @return mixed
50 | */
51 | public function byDepartment($id, $dates)
52 | {
53 | return $this->client->postJson('topapi/health/stepinfo/list', ['type' => 1, 'object_id' => $id, 'stat_dates' => $dates]);
54 | }
55 |
56 | /**
57 | * 批量获取钉钉运动数据
58 | *
59 | * @param array $userIds
60 | * @param string $date
61 | *
62 | * @return mixed
63 | */
64 | public function byUsers(array $userIds, $date)
65 | {
66 | $userIds = implode(',', $userIds);
67 |
68 | return $this->client->postJson('topapi/health/stepinfo/listbyuserid', ['userids' => $userIds, 'stat_date' => $date]);
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/Health/ServiceProvider.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Health;
13 |
14 | use Pimple\Container;
15 | use Pimple\ServiceProviderInterface;
16 |
17 | class ServiceProvider implements ServiceProviderInterface
18 | {
19 | /**
20 | * Registers services on the given container.
21 | * This method should only be used to configure services and parameters.
22 | * It should not get services.
23 | *
24 | * @param \Pimple\Container $pimple A container instance
25 | */
26 | public function register(Container $pimple)
27 | {
28 | $pimple['health'] = function ($app) {
29 | return new Client($app);
30 | };
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/Kernel/AccessToken.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Kernel;
13 |
14 | use EasyDingTalk\Kernel\Exceptions\InvalidCredentialsException;
15 | use EasyDingTalk\Kernel\Http\Client;
16 | use function EasyDingTalk\tap;
17 | use Overtrue\Http\Traits\ResponseCastable;
18 |
19 | class AccessToken
20 | {
21 | use Concerns\InteractsWithCache, ResponseCastable;
22 |
23 | /**
24 | * @var \EasyDingTalk\Application
25 | */
26 | protected $app;
27 |
28 | /**
29 | * AccessToken constructor.
30 | *
31 | * @param \EasyDingTalk\Application
32 | */
33 | public function __construct($app)
34 | {
35 | $this->app = $app;
36 | }
37 |
38 | /**
39 | * 获取钉钉 AccessToken
40 | *
41 | * @return array
42 | *
43 | * @throws \Psr\SimpleCache\InvalidArgumentException
44 | */
45 | public function get()
46 | {
47 | if ($value = $this->getCache()->get($this->cacheFor())) {
48 | return $value;
49 | }
50 |
51 | return $this->refresh();
52 | }
53 |
54 | /**
55 | * 获取 AccessToken
56 | *
57 | * @return string
58 | *
59 | * @throws \Psr\SimpleCache\InvalidArgumentException
60 | */
61 | public function getToken()
62 | {
63 | return $this->get()['access_token'];
64 | }
65 |
66 | /**
67 | * 刷新钉钉 AccessToken
68 | *
69 | * @return array
70 | */
71 | public function refresh()
72 | {
73 | $response = (new Client($this->app))->requestRaw('gettoken', 'GET', ['query' => [
74 | 'appkey' => $this->app['config']->get('app_key'),
75 | 'appsecret' => $this->app['config']->get('app_secret'),
76 | ]]);
77 |
78 | return tap($this->castResponseToType($response, 'array'), function ($value) {
79 | if (0 !== $value['errcode']) {
80 | throw new InvalidCredentialsException(json_encode($value));
81 | }
82 | $this->getCache()->set($this->cacheFor(), $value, $value['expires_in']);
83 | });
84 | }
85 |
86 | /**
87 | * 缓存 Key
88 | *
89 | * @return string
90 | */
91 | protected function cacheFor()
92 | {
93 | return sprintf('access_token.%s', $this->app['config']->get('app_key'));
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/src/Kernel/BaseClient.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Kernel;
13 |
14 | class BaseClient
15 | {
16 | /**
17 | * @var \EasyDingTalk\Application
18 | */
19 | protected $app;
20 |
21 | /**
22 | * @var \EasyDingTalk\Kernel\Http\Client
23 | */
24 | protected $client;
25 |
26 | /**
27 | * Client constructor.
28 | *
29 | * @param \EasyDingTalk\Application $app
30 | */
31 | public function __construct($app)
32 | {
33 | $this->app = $app;
34 | $this->client = $this->app['client']->withAccessTokenMiddleware()->withRetryMiddleware();
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/Kernel/Concerns/InteractsWithCache.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Kernel\Concerns;
13 |
14 | use Psr\SimpleCache\CacheInterface;
15 | use Symfony\Component\Cache\Adapter\FilesystemAdapter;
16 | use Symfony\Component\Cache\Psr16Cache;
17 | use Symfony\Component\Cache\Simple\FilesystemCache;
18 |
19 | trait InteractsWithCache
20 | {
21 | /**
22 | * @var \Psr\SimpleCache\CacheInterface
23 | */
24 | protected $cache;
25 |
26 | /**
27 | * @return \Psr\SimpleCache\CacheInterface
28 | */
29 | public function getCache()
30 | {
31 | if ($this->cache) {
32 | return $this->cache;
33 | }
34 |
35 | if (property_exists($this, 'app') && $this->app->offsetExists('cache') && ($this->app['cache'] instanceof CacheInterface)) {
36 | return $this->cache = $this->app['cache'];
37 | }
38 |
39 | return $this->cache = $this->createDefaultCache();
40 | }
41 |
42 | /**
43 | * @return \Psr\SimpleCache\CacheInterface
44 | */
45 | protected function createDefaultCache()
46 | {
47 | if (class_exists(Psr16Cache::class)) {
48 | return new Psr16Cache(new FilesystemAdapter('easydingtalk'));
49 | }
50 |
51 | return new FilesystemCache('easydingtalk');
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/Kernel/Encryption/Encryptor.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Kernel\Encryption;
13 |
14 | use function EasyDingTalk\str_random;
15 |
16 | class Encryptor
17 | {
18 | /**
19 | * @var string
20 | */
21 | protected $key;
22 |
23 | /**
24 | * @var string
25 | */
26 | protected $token;
27 |
28 | /**
29 | * @var string
30 | */
31 | protected $aesKey;
32 |
33 | /**
34 | * @var int
35 | */
36 | protected $blockSize = 32;
37 |
38 | /**
39 | * Encryptor Constructor.
40 | *
41 | * @param string $key
42 | * @param string $token
43 | * @param string $aesKey
44 | */
45 | public function __construct($key, $token, $aesKey)
46 | {
47 | $this->key = $key;
48 | $this->token = $token;
49 | $this->aesKey = base64_decode($aesKey.'=', true);
50 | }
51 |
52 | /**
53 | * Encrypt the data.
54 | *
55 | * @param string $data
56 | * @param string $nonce
57 | * @param int $timestamp
58 | *
59 | * @return string
60 | */
61 | public function encrypt($data, $nonce = null, $timestamp = null)
62 | {
63 | $string = str_random().pack('N', strlen($data)).$data.$this->key;
64 |
65 | $result = base64_encode(
66 | openssl_encrypt($this->pkcs7Pad($string), 'AES-256-CBC', $this->aesKey, OPENSSL_NO_PADDING, substr($this->aesKey, 0, 16))
67 | );
68 |
69 | !is_null($nonce) || $nonce = uniqid();
70 | !is_null($timestamp) || $timestamp = time();
71 |
72 | return json_encode([
73 | 'msg_signature' => $this->signature($this->token, $nonce, $timestamp, $result),
74 | 'timeStamp' => $timestamp,
75 | 'nonce' => $nonce,
76 | 'encrypt' => $result,
77 | ]);
78 | }
79 |
80 | /**
81 | * Decrypt the data.
82 | *
83 | * @param string $data
84 | * @param string $signature
85 | * @param string $nonce
86 | * @param int $timestamp
87 | *
88 | * @return string
89 | */
90 | public function decrypt($data, $signature, $nonce, $timestamp)
91 | {
92 | if ($signature !== $this->signature($this->token, $nonce, $timestamp, $data)) {
93 | throw new \RuntimeException('Invalid Signature.');
94 | }
95 |
96 | $decrypted = openssl_decrypt(
97 | base64_decode($data, true), 'AES-256-CBC', $this->aesKey, OPENSSL_NO_PADDING, substr($this->aesKey, 0, 16)
98 | );
99 |
100 | $result = $this->pkcs7Unpad($decrypted);
101 |
102 | $data = substr($result, 16, strlen($result));
103 |
104 | $contentLen = unpack('N', substr($data, 0, 4))[1];
105 |
106 | if (substr($data, $contentLen + 4) !== $this->key) {
107 | throw new \RuntimeException('Invalid CorpId.');
108 | }
109 |
110 | return substr($data, 4, $contentLen);
111 | }
112 |
113 | /**
114 | * Get SHA1.
115 | *
116 | * @return string
117 | */
118 | public function signature()
119 | {
120 | $array = func_get_args();
121 | sort($array, SORT_STRING);
122 |
123 | return sha1(implode($array));
124 | }
125 |
126 | /**
127 | * PKCS#7 pad.
128 | *
129 | * @param string $text
130 | *
131 | * @return string
132 | */
133 | public function pkcs7Pad(string $text)
134 | {
135 | $padding = $this->blockSize - (strlen($text) % $this->blockSize);
136 | $pattern = chr($padding);
137 |
138 | return $text.str_repeat($pattern, $padding);
139 | }
140 |
141 | /**
142 | * PKCS#7 unpad.
143 | *
144 | * @param string $text
145 | *
146 | * @return string
147 | */
148 | public function pkcs7Unpad(string $text)
149 | {
150 | $pad = ord(substr($text, -1));
151 | if ($pad < 1 || $pad > $this->blockSize) {
152 | $pad = 0;
153 | }
154 |
155 | return substr($text, 0, (strlen($text) - $pad));
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/src/Kernel/Exceptions/Exception.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Kernel\Exceptions;
13 |
14 | use Exception as BaseException;
15 |
16 | class Exception extends BaseException
17 | {
18 | //
19 | }
20 |
--------------------------------------------------------------------------------
/src/Kernel/Exceptions/InvalidArgumentException.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Kernel\Exceptions;
13 |
14 | class InvalidArgumentException extends Exception
15 | {
16 | //
17 | }
18 |
--------------------------------------------------------------------------------
/src/Kernel/Exceptions/InvalidCredentialsException.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Kernel\Exceptions;
13 |
14 | class InvalidCredentialsException extends Exception
15 | {
16 | //
17 | }
18 |
--------------------------------------------------------------------------------
/src/Kernel/Exceptions/RuntimeException.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Kernel\Exceptions;
13 |
14 | class RuntimeException extends Exception
15 | {
16 | //
17 | }
18 |
--------------------------------------------------------------------------------
/src/Kernel/Http/Client.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Kernel\Http;
13 |
14 | use GuzzleHttp\Middleware;
15 | use Overtrue\Http\Client as BaseClient;
16 | use Psr\Http\Message\RequestInterface;
17 | use Psr\Http\Message\ResponseInterface;
18 |
19 | class Client extends BaseClient
20 | {
21 | /**
22 | * @var \EasyDingTalk\Application
23 | */
24 | protected $app;
25 |
26 | /**
27 | * @var array
28 | */
29 | protected static $httpConfig = [
30 | 'base_uri' => 'https://oapi.dingtalk.com',
31 | ];
32 |
33 | /**
34 | * @param \EasyDingTalk\Application $app
35 | */
36 | public function __construct($app)
37 | {
38 | $this->app = $app;
39 |
40 | parent::__construct(array_merge(static::$httpConfig, $this->app['config']->get('http', [])));
41 | }
42 |
43 | /**
44 | * @param array $config
45 | */
46 | public function setHttpConfig(array $config)
47 | {
48 | static::$httpConfig = array_merge(static::$httpConfig, $config);
49 | }
50 |
51 | /**
52 | * @return $this
53 | */
54 | public function withAccessTokenMiddleware()
55 | {
56 | if (isset($this->getMiddlewares()['access_token'])) {
57 | return $this;
58 | }
59 |
60 | $middleware = function (callable $handler) {
61 | return function (RequestInterface $request, array $options) use ($handler) {
62 | if ($this->app['access_token']) {
63 | parse_str($request->getUri()->getQuery(), $query);
64 |
65 | $request = $request->withUri(
66 | $request->getUri()->withQuery(http_build_query(['access_token' => $this->app['access_token']->getToken()] + $query))
67 | );
68 | }
69 |
70 | return $handler($request, $options);
71 | };
72 | };
73 |
74 | $this->pushMiddleware($middleware, 'access_token');
75 |
76 | return $this;
77 | }
78 |
79 | /**
80 | * @return $this
81 | */
82 | public function withRetryMiddleware()
83 | {
84 | if (isset($this->getMiddlewares()['retry'])) {
85 | return $this;
86 | }
87 |
88 | $middleware = Middleware::retry(function ($retries, RequestInterface $request, ResponseInterface $response = null) {
89 | if (is_null($response) || $retries < 1) {
90 | return false;
91 | }
92 |
93 | if (in_array(json_decode($response->getBody(), true)['errcode'] ?? null, [40001])) {
94 | $this->app['access_token']->refresh();
95 |
96 | return true;
97 | }
98 | });
99 |
100 | $this->pushMiddleware($middleware, 'retry');
101 |
102 | return $this;
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/src/Kernel/Providers/AccessTokenServiceProvider.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Kernel\Providers;
13 |
14 | use EasyDingTalk\Kernel\AccessToken;
15 | use Pimple\Container;
16 | use Pimple\ServiceProviderInterface;
17 |
18 | class AccessTokenServiceProvider implements ServiceProviderInterface
19 | {
20 | /**
21 | * Registers services on the given container.
22 | * This method should only be used to configure services and parameters.
23 | * It should not get services.
24 | *
25 | * @param \Pimple\Container $pimple A container instance
26 | */
27 | public function register(Container $pimple)
28 | {
29 | isset($pimple['access_token']) || $pimple['access_token'] = function ($app) {
30 | return new AccessToken($app);
31 | };
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/Kernel/Providers/ClientServiceProvider.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Kernel\Providers;
13 |
14 | use EasyDingTalk\Kernel\Http\Client;
15 | use Pimple\Container;
16 | use Pimple\ServiceProviderInterface;
17 |
18 | class ClientServiceProvider implements ServiceProviderInterface
19 | {
20 | /**
21 | * Registers services on the given container.
22 | * This method should only be used to configure services and parameters.
23 | * It should not get services.
24 | *
25 | * @param \Pimple\Container $pimple A container instance
26 | */
27 | public function register(Container $pimple)
28 | {
29 | isset($pimple['client']) || $pimple['client'] = function ($app) {
30 | return new Client($app);
31 | };
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/Kernel/Providers/EncryptionServiceProvider.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Kernel\Providers;
13 |
14 | use EasyDingTalk\Kernel\Encryption\Encryptor;
15 | use Pimple\Container;
16 | use Pimple\ServiceProviderInterface;
17 |
18 | class EncryptionServiceProvider implements ServiceProviderInterface
19 | {
20 | /**
21 | * Registers services on the given container.
22 | * This method should only be used to configure services and parameters.
23 | * It should not get services.
24 | *
25 | * @param \Pimple\Container $pimple A container instance
26 | */
27 | public function register(Container $pimple)
28 | {
29 | $pimple['encryptor'] = function ($app) {
30 | return new Encryptor(
31 | $app['config']->get('corp_id'),
32 | $app['config']->get('token'),
33 | $app['config']->get('aes_key')
34 | );
35 | };
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/Kernel/Providers/LoggerServiceProvider.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Kernel\Providers;
13 |
14 | use Monolog\Logger;
15 | use Pimple\Container;
16 | use Pimple\ServiceProviderInterface;
17 |
18 | class LoggerServiceProvider implements ServiceProviderInterface
19 | {
20 | /**
21 | * Registers services on the given container.
22 | * This method should only be used to configure services and parameters.
23 | * It should not get services.
24 | *
25 | * @param \Pimple\Container $pimple A container instance
26 | */
27 | public function register(Container $pimple)
28 | {
29 | isset($pimple['logger']) || $pimple['logger'] = function ($app) {
30 | return new Logger('EasyDingTalk');
31 | };
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/Kernel/Providers/RequestServiceProvider.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Kernel\Providers;
13 |
14 | use Pimple\Container;
15 | use Pimple\ServiceProviderInterface;
16 | use Symfony\Component\HttpFoundation\Request;
17 |
18 | class RequestServiceProvider implements ServiceProviderInterface
19 | {
20 | /**
21 | * Registers services on the given container.
22 | * This method should only be used to configure services and parameters.
23 | * It should not get services.
24 | *
25 | * @param \Pimple\Container $pimple A container instance
26 | */
27 | public function register(Container $pimple)
28 | {
29 | $pimple['request'] = function ($app) {
30 | return Request::createFromGlobals();
31 | };
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/Kernel/Providers/ServerServiceProvider.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Kernel\Providers;
13 |
14 | use EasyDingTalk\Kernel\Server;
15 | use Pimple\Container;
16 | use Pimple\ServiceProviderInterface;
17 |
18 | class ServerServiceProvider implements ServiceProviderInterface
19 | {
20 | /**
21 | * Registers services on the given container.
22 | * This method should only be used to configure services and parameters.
23 | * It should not get services.
24 | *
25 | * @param \Pimple\Container $pimple A container instance
26 | */
27 | public function register(Container $pimple)
28 | {
29 | $pimple['server'] = function ($app) {
30 | return new Server($app);
31 | };
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/Kernel/Server.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Kernel;
13 |
14 | use EasyDingTalk\Kernel\Exceptions\InvalidArgumentException;
15 | use EasyDingTalk\Kernel\Exceptions\RuntimeException;
16 | use function EasyDingTalk\tap;
17 | use Symfony\Component\HttpFoundation\Response;
18 |
19 | class Server
20 | {
21 | /**
22 | * @var \EasyDingTalk\Application
23 | */
24 | protected $app;
25 |
26 | /**
27 | * @var array
28 | */
29 | protected $handlers = [];
30 |
31 | /**
32 | * @param \EasyDingTalk\Application $app
33 | */
34 | public function __construct($app)
35 | {
36 | $this->app = $app;
37 | }
38 |
39 | /**
40 | * Handle the request.
41 | *
42 | * @return \Symfony\Component\HttpFoundation\Response
43 | */
44 | public function serve()
45 | {
46 | foreach ($this->handlers as $handler) {
47 | $handler->__invoke($this->getPayload());
48 | }
49 |
50 | $this->app['logger']->debug('Request received: ', [
51 | 'method' => $this->app['request']->getMethod(),
52 | 'uri' => $this->app['request']->getUri(),
53 | 'content' => $this->app['request']->getContent(),
54 | ]);
55 |
56 | return tap(new Response(
57 | $this->app['encryptor']->encrypt('success'), 200, ['Content-Type' => 'application/json']
58 | ), function ($response) {
59 | $this->app['logger']->debug('Response created:', ['content' => $response->getContent()]);
60 | });
61 | }
62 |
63 | /**
64 | * Push handler.
65 | *
66 | * @param \Closure|string|object $handler
67 | *
68 | * @return void
69 | *
70 | * @throws \EasyDingTalk\Kernel\Exceptions\InvalidArgumentException
71 | */
72 | public function push($handler)
73 | {
74 | if (is_string($handler)) {
75 | $handler = function ($payload) use ($handler) {
76 | return (new $handler($this->app))->__invoke($payload);
77 | };
78 | }
79 |
80 | if (!is_callable($handler)) {
81 | throw new InvalidArgumentException('Invalid handler');
82 | }
83 |
84 | array_push($this->handlers, $handler);
85 | }
86 |
87 | /**
88 | * Get request payload.
89 | *
90 | * @return array
91 | */
92 | public function getPayload()
93 | {
94 | $payload = json_decode($this->app['request']->getContent(), true);
95 |
96 | if (JSON_ERROR_NONE !== json_last_error()) {
97 | throw new RuntimeException('No payload received');
98 | }
99 |
100 | $result = $this->app['encryptor']->decrypt(
101 | $payload['encrypt'], $this->app['request']->get('signature'), $this->app['request']->get('nonce'), $this->app['request']->get('timestamp')
102 | );
103 |
104 | return json_decode($result, true);
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/src/Media/Client.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Media;
13 |
14 | use EasyDingTalk\Kernel\BaseClient;
15 |
16 | class Client extends BaseClient
17 | {
18 | /**
19 | * 上传图片
20 | *
21 | * @param mixed $media
22 | *
23 | * @return mixed
24 | */
25 | public function uploadImage($media)
26 | {
27 | return $this->upload('image', $media);
28 | }
29 |
30 | /**
31 | * 上传语音
32 | *
33 | * @param mixed $media
34 | *
35 | * @return mixed
36 | */
37 | public function uploadVoice($media)
38 | {
39 | return $this->upload('voice', $media);
40 | }
41 |
42 | /**
43 | * 上传普通文件
44 | *
45 | * @param mixed $media
46 | *
47 | * @return mixed
48 | */
49 | public function uploadFile($media)
50 | {
51 | return $this->upload('file', $media);
52 | }
53 |
54 | /**
55 | * 上传媒体文件
56 | *
57 | * @param string $type
58 | * @param mixed $media
59 | *
60 | * @return mixed
61 | */
62 | public function upload($type, $media)
63 | {
64 | return $this->client->upload('media/upload', ['media' => $media], compact('type'));
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/Media/ServiceProvider.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Media;
13 |
14 | use Pimple\Container;
15 | use Pimple\ServiceProviderInterface;
16 |
17 | class ServiceProvider implements ServiceProviderInterface
18 | {
19 | /**
20 | * Registers services on the given container.
21 | * This method should only be used to configure services and parameters.
22 | * It should not get services.
23 | *
24 | * @param \Pimple\Container $pimple A container instance
25 | */
26 | public function register(Container $pimple)
27 | {
28 | $pimple['media'] = function ($app) {
29 | return new Client($app);
30 | };
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/Messages/File.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Messages;
13 |
14 | class File extends Message
15 | {
16 | protected $type = 'file';
17 |
18 | protected function transform($value)
19 | {
20 | list($mediaId) = $value;
21 |
22 | return ['media_id' => $mediaId];
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/Messages/Image.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Messages;
13 |
14 | class Image extends Message
15 | {
16 | protected $type = 'image';
17 |
18 | protected function transform($value)
19 | {
20 | list($mediaId) = $value;
21 |
22 | return ['media_id' => $mediaId];
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/Messages/Link.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Messages;
13 |
14 | class Link extends Message
15 | {
16 | protected $type = 'link';
17 |
18 | public function setPictureUrl($value)
19 | {
20 | return $this->setAttribute('picUrl', $value);
21 | }
22 |
23 | public function setTitle($value)
24 | {
25 | return $this->setAttribute('title', $value);
26 | }
27 |
28 | public function setText($value)
29 | {
30 | return $this->setAttribute('text', $value);
31 | }
32 |
33 | protected function transform($value)
34 | {
35 | list($url) = $value;
36 |
37 | return ['messageUrl' => $url];
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/Messages/Message.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Messages;
13 |
14 | class Message
15 | {
16 | protected $value;
17 | protected $type;
18 | protected $attributes = [];
19 |
20 | public function __construct(...$value)
21 | {
22 | $this->value = $value;
23 | }
24 |
25 | public static function make()
26 | {
27 | return new static(...func_get_args());
28 | }
29 |
30 | public function type()
31 | {
32 | return $this->type;
33 | }
34 |
35 | protected function transform($value)
36 | {
37 | return $value;
38 | }
39 |
40 | public function setAttribute($key, $value)
41 | {
42 | $this->attributes[$key] = $value;
43 |
44 | return $this;
45 | }
46 |
47 | public function toArray()
48 | {
49 | return [
50 | 'msgtype' => $this->type(),
51 | $this->type() => array_merge($this->transform($this->value), $this->attributes),
52 | ];
53 | }
54 |
55 | public function toJson()
56 | {
57 | return json_encode($this->toArray());
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/Messages/Text.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Messages;
13 |
14 | class Text extends Message
15 | {
16 | protected $type = 'text';
17 |
18 | protected function transform($value)
19 | {
20 | list($content) = $value;
21 |
22 | return ['content' => $content];
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/Messages/Voice.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Messages;
13 |
14 | class Voice extends Message
15 | {
16 | protected $type = 'voice';
17 |
18 | protected function transform($value)
19 | {
20 | list($mediaId, $duration) = $value;
21 |
22 | return ['media_id' => $mediaId, 'duration' => $duration];
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/Microapp/Client.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Microapp;
13 |
14 | use EasyDingTalk\Kernel\BaseClient;
15 |
16 | class Client extends BaseClient
17 | {
18 | /**
19 | * 获取应用列表
20 | *
21 | * @return mixed
22 | */
23 | public function list()
24 | {
25 | return $this->client->postJson('microapp/list');
26 | }
27 |
28 | /**
29 | * 获取员工可见的应用列表
30 | *
31 | * @param string $userId
32 | *
33 | * @return mixed
34 | */
35 | public function listByUserId($userId)
36 | {
37 | return $this->client->get('microapp/list_by_userid', [
38 | 'userid' => $userId,
39 | ]);
40 | }
41 |
42 | /**
43 | * 获取应用的可见范围
44 | *
45 | * @param int $agentId
46 | *
47 | * @return mixed
48 | */
49 | public function getVisibility($agentId)
50 | {
51 | return $this->client->postJson('microapp/visible_scopes', compact('agentId'));
52 | }
53 |
54 | /**
55 | * 设置应用的可见范围
56 | *
57 | * @param array $params
58 | *
59 | * @return mixed
60 | */
61 | public function setVisibility($params)
62 | {
63 | return $this->client->postJson('microapp/set_visible_scopes', $params);
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/Microapp/ServiceProvider.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Microapp;
13 |
14 | use Pimple\Container;
15 | use Pimple\ServiceProviderInterface;
16 |
17 | class ServiceProvider implements ServiceProviderInterface
18 | {
19 | /**
20 | * Registers services on the given container.
21 | * This method should only be used to configure services and parameters.
22 | * It should not get services.
23 | *
24 | * @param \Pimple\Container $pimple A container instance
25 | */
26 | public function register(Container $pimple)
27 | {
28 | $pimple['microapp'] = function ($app) {
29 | return new Client($app);
30 | };
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/Process/Client.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Process;
13 |
14 | use EasyDingTalk\Kernel\BaseClient;
15 |
16 | class Client extends BaseClient
17 | {
18 | /**
19 | * 发起审批实例
20 | *
21 | * @param array $params
22 | *
23 | * @return mixed
24 | */
25 | public function create($params)
26 | {
27 | return $this->client->postJson('topapi/processinstance/create', $params);
28 | }
29 |
30 | /**
31 | * 批量获取审批实例 ID
32 | *
33 | * @param array $params
34 | *
35 | * @return mixed
36 | */
37 | public function getIds($params)
38 | {
39 | return $this->client->postJson('topapi/processinstance/listids', $params);
40 | }
41 |
42 | /**
43 | * 获取单个审批实例
44 | *
45 | * @param string $id
46 | *
47 | * @return mixed
48 | */
49 | public function get($id)
50 | {
51 | return $this->client->postJson('topapi/processinstance/get', ['process_instance_id' => $id]);
52 | }
53 |
54 | /**
55 | * 获取用户待审批数量
56 | *
57 | * @param string $userId
58 | *
59 | * @return mixed
60 | */
61 | public function count($userId)
62 | {
63 | return $this->client->postJson('topapi/process/gettodonum', ['userid' => $userId]);
64 | }
65 |
66 | /**
67 | * 获取用户可见的审批模板
68 | *
69 | * @param string|null $userId
70 | * @param int $offset
71 | * @param int $size
72 | *
73 | * @return mixed
74 | */
75 | public function listByUserId($userId = null, $offset = 0, $size = 100)
76 | {
77 | return $this->client->postJson('topapi/process/listbyuserid', ['userid' => $userId, 'offset' => $offset, 'size' => $size]);
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/Process/ServiceProvider.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Process;
13 |
14 | use Pimple\Container;
15 | use Pimple\ServiceProviderInterface;
16 |
17 | class ServiceProvider implements ServiceProviderInterface
18 | {
19 | /**
20 | * Registers services on the given container.
21 | * This method should only be used to configure services and parameters.
22 | * It should not get services.
23 | *
24 | * @param \Pimple\Container $pimple A container instance
25 | */
26 | public function register(Container $pimple)
27 | {
28 | $pimple['process'] = function ($app) {
29 | return new Client($app);
30 | };
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/Report/Client.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Report;
13 |
14 | use EasyDingTalk\Kernel\BaseClient;
15 |
16 | class Client extends BaseClient
17 | {
18 | /**
19 | * 获取用户日志数据
20 | *
21 | * @param array $params
22 | *
23 | * @return mixed
24 | */
25 | public function list($params)
26 | {
27 | return $this->client->postJson('topapi/report/list', $params);
28 | }
29 |
30 | /**
31 | * 获取用户可见的日志模板
32 | *
33 | * @param string|null $userId
34 | * @param int $offset
35 | * @param int $size
36 | *
37 | * @return mixed
38 | */
39 | public function templates($userId = null, $offset = 0, $size = 100)
40 | {
41 | return $this->client->postJson('topapi/report/template/listbyuserid', [
42 | 'userid' => $userId, 'offset' => $offset, 'size' => $size,
43 | ]);
44 | }
45 |
46 | /**
47 | * 获取用户日志未读数
48 | *
49 | * @param string $userid
50 | *
51 | * @return mixed
52 | */
53 | public function unreadCount($userid)
54 | {
55 | return $this->client->postJson('topapi/report/getunreadcount', compact('userid'));
56 | }
57 |
58 | /**
59 | * 获取日志的已读人数、评论条数、评论人数、点赞人数。
60 | *
61 | * @param $report_id
62 | *
63 | * @return mixed
64 | */
65 | public function statistics($report_id)
66 | {
67 | return $this->client->postJson('topapi/report/statistics', compact('report_id'));
68 | }
69 |
70 | /**
71 | * 获取日志相关人员列表,包括已读人员列表、评论人员列表、点赞人员列表
72 | *
73 | * @param string $report_id
74 | * @param int $type
75 | * @param int $offset
76 | * @param int $size
77 | *
78 | * @return mixed
79 | */
80 | public function statisticsByType($report_id, $type, $offset = 0, $size = 100)
81 | {
82 | return $this->client->postJson('topapi/report/statistics/listbytype', [
83 | 'report_id' => $report_id, 'type' => $type, 'offset' => $offset, 'size' => $size
84 | ]);
85 | }
86 |
87 | /**
88 | * 获取日志接收人员列表
89 | *
90 | * @param string $report_id
91 | * @param int $offset
92 | * @param int $size
93 | *
94 | * @return mixed
95 | */
96 | public function getReceivers($report_id, $offset = 0, $size = 100)
97 | {
98 | return $this->client->postJson('topapi/report/receiver/list', [
99 | 'report_id' => $report_id, 'offset' => $offset, 'size' => $size
100 | ]);
101 | }
102 |
103 | /**
104 | * 获取日志评论详情,包括评论人userid、评论内容、评论时间
105 | *
106 | * @param string $report_id
107 | * @param int $offset
108 | * @param int $size
109 | *
110 | * @return mixed
111 | */
112 | public function getComments($report_id, $offset = 0, $size = 100)
113 | {
114 | return $this->client->postJson('topapi/report/comment/list', [
115 | 'report_id' => $report_id, 'offset' => $offset, 'size' => $size
116 | ]);
117 | }
118 |
119 | }
120 |
--------------------------------------------------------------------------------
/src/Report/ServiceProvider.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Report;
13 |
14 | use Pimple\Container;
15 | use Pimple\ServiceProviderInterface;
16 |
17 | class ServiceProvider implements ServiceProviderInterface
18 | {
19 | /**
20 | * Registers services on the given container.
21 | * This method should only be used to configure services and parameters.
22 | * It should not get services.
23 | *
24 | * @param \Pimple\Container $pimple A container instance
25 | */
26 | public function register(Container $pimple)
27 | {
28 | $pimple['report'] = function ($app) {
29 | return new Client($app);
30 | };
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/Robot.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk;
13 |
14 | use Overtrue\Http\Traits\HasHttpRequests;
15 |
16 | class Robot
17 | {
18 | use HasHttpRequests;
19 |
20 | /**
21 | * 机器人 AccessToken
22 | *
23 | * @var string
24 | */
25 | protected $accessToken;
26 |
27 | /**
28 | * 加签 没有勾选,不用填写
29 | *
30 | * @var string
31 | */
32 | protected $secret;
33 |
34 | /**
35 | * @param string $accessToken
36 | * @param string|null $secret
37 | */
38 | public function __construct($accessToken, $secret = null)
39 | {
40 | $this->accessToken = $accessToken;
41 | $this->secret = $secret;
42 | }
43 |
44 | /**
45 | * @param string $accessToken
46 | * @param string|null $secret
47 | *
48 | * @return self
49 | */
50 | public static function create($accessToken, $secret = null)
51 | {
52 | return new static($accessToken, $secret);
53 | }
54 |
55 | /**
56 | * 发送消息
57 | *
58 | * @param array $message
59 | *
60 | * @return array
61 | *
62 | * @throws \GuzzleHttp\Exception\GuzzleException
63 | */
64 | public function send($message)
65 | {
66 | $url = 'https://oapi.dingtalk.com/robot/send?access_token='.$this->accessToken;
67 |
68 | if ($this->secret) {
69 | $timestamp = time().'000';
70 | $url .= sprintf(
71 | '&sign=%s×tamp=%s',
72 | urlencode(base64_encode(hash_hmac('sha256', $timestamp."\n".$this->secret, $this->secret, true))), $timestamp
73 | );
74 | }
75 |
76 | $response = $this->getHttpClient()->request(
77 | 'POST', $url, ['json' => $message]
78 | );
79 |
80 | return $this->castResponseToType($response);
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/Role/Client.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Role;
13 |
14 | use EasyDingTalk\Kernel\BaseClient;
15 |
16 | class Client extends BaseClient
17 | {
18 | /**
19 | * 获取角色列表
20 | *
21 | * @param int $offset
22 | * @param int $size
23 | *
24 | * @return mixed
25 | */
26 | public function list($offset = null, $size = null)
27 | {
28 | return $this->client->postJson('topapi/role/list', compact('offset', 'size'));
29 | }
30 |
31 | /**
32 | * 获取角色下的员工列表
33 | *
34 | * @param int $roleId
35 | * @param int $offset
36 | * @param int $size
37 | *
38 | * @return mixed
39 | */
40 | public function getUsers($roleId, $offset = null, $size = null)
41 | {
42 | return $this->client->postJson('topapi/role/simplelist', compact('offset', 'size') + ['role_id' => $roleId]);
43 | }
44 |
45 | /**
46 | * 获取角色组
47 | *
48 | * @param int $groupId
49 | *
50 | * @return mixed
51 | */
52 | public function getGroups($groupId)
53 | {
54 | return $this->client->postJson('topapi/role/getrolegroup', ['group_id' => $groupId]);
55 | }
56 |
57 | /**
58 | * 获取角色详情
59 | *
60 | * @param int $roleId
61 | *
62 | * @return mixed
63 | */
64 | public function get($roleId)
65 | {
66 | return $this->client->postJson('topapi/role/getrole', compact('roleId'));
67 | }
68 |
69 | /**
70 | * 创建角色
71 | *
72 | * @param int $groupId
73 | * @param string $roleName
74 | *
75 | * @return mixed
76 | */
77 | public function create($groupId, $roleName)
78 | {
79 | return $this->client->postJson('role/add_role', compact('groupId', 'roleName'));
80 | }
81 |
82 | /**
83 | * 更新角色
84 | *
85 | * @param int $roleId
86 | * @param string $roleName
87 | *
88 | * @return mixed
89 | */
90 | public function update($roleId, $roleName)
91 | {
92 | return $this->client->postJson('role/update_role', compact('roleId', 'roleName'));
93 | }
94 |
95 | /**
96 | * 删除角色
97 | *
98 | * @param int $roleId
99 | *
100 | * @return mixed
101 | */
102 | public function delete($roleId)
103 | {
104 | return $this->client->postJson('topapi/role/deleterole', ['role_id' => $roleId]);
105 | }
106 |
107 | /**
108 | * 创建角色组
109 | *
110 | * @param string $name
111 | *
112 | * @return mixed
113 | */
114 | public function createGroup($name)
115 | {
116 | return $this->client->postJson('role/add_role_group', compact('name'));
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/src/Role/ServiceProvider.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Role;
13 |
14 | use Pimple\Container;
15 | use Pimple\ServiceProviderInterface;
16 |
17 | class ServiceProvider implements ServiceProviderInterface
18 | {
19 | /**
20 | * Registers services on the given container.
21 | * This method should only be used to configure services and parameters.
22 | * It should not get services.
23 | *
24 | * @param \Pimple\Container $pimple A container instance
25 | */
26 | public function register(Container $pimple)
27 | {
28 | $pimple['role'] = function ($app) {
29 | return new Client($app);
30 | };
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/Schedule/Client.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Schedule;
13 |
14 | use EasyDingTalk\Kernel\BaseClient;
15 |
16 | class Client extends BaseClient
17 | {
18 | /**
19 | * 发起待办
20 | *
21 | * @param array $params
22 | *
23 | * @return mixed
24 | */
25 | public function add($params)
26 | {
27 | return $this->client->postJson('topapi/workrecord/add', $params);
28 | }
29 |
30 | /**
31 | * 更新待办
32 | *
33 | * @param string $userId
34 | * @param string $recordId
35 | *
36 | * @return mixed
37 | */
38 | public function update($userId, $recordId)
39 | {
40 | return $this->client->postJson('topapi/workrecord/update', ['userid' => $userId, 'record_id' => $recordId]);
41 | }
42 |
43 | /**
44 | * 获取用户待办事项
45 | *
46 | * @param string $userId
47 | * @param bool $completed
48 | * @param int $offset
49 | * @param int $limit
50 | *
51 | * @return mixed
52 | */
53 | public function list($userId, $completed, $offset, $limit)
54 | {
55 | return $this->client->postJson('topapi/workrecord/getbyuserid', [
56 | 'userid' => $userId,
57 | 'status' => (int) $completed,
58 | 'offset' => $offset,
59 | 'limit' => $limit,
60 | ]);
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/Schedule/ServiceProvider.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Schedule;
13 |
14 | use Pimple\Container;
15 | use Pimple\ServiceProviderInterface;
16 |
17 | class ServiceProvider implements ServiceProviderInterface
18 | {
19 | /**
20 | * Registers services on the given container.
21 | * This method should only be used to configure services and parameters.
22 | * It should not get services.
23 | *
24 | * @param \Pimple\Container $pimple A container instance
25 | */
26 | public function register(Container $pimple)
27 | {
28 | $pimple['schedule'] = function ($app) {
29 | return new Client($app);
30 | };
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/User/Client.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\User;
13 |
14 | use EasyDingTalk\Kernel\BaseClient;
15 |
16 | class Client extends BaseClient
17 | {
18 | /**
19 | * 获取用户详情
20 | *
21 | * @param string $userid
22 | * @param string|null $lang
23 | *
24 | * @return mixed
25 | */
26 | public function get($userid, $lang = null)
27 | {
28 | return $this->client->get('user/get', compact('userid', 'lang'));
29 | }
30 |
31 | /**
32 | * 获取部门用户 Userid 列表
33 | *
34 | * @param int $departmentId
35 | *
36 | * @return mixed
37 | */
38 | public function getUserIds($departmentId)
39 | {
40 | return $this->client->get('user/getDeptMember', ['deptId' => $departmentId]);
41 | }
42 |
43 | /**
44 | * 获取部门用户
45 | *
46 | * @param int $departmentId
47 | * @param int $offset
48 | * @param int $size
49 | * @param string $order
50 | * @param string $lang
51 | *
52 | * @return mixed
53 | */
54 | public function getUsers($departmentId, $offset, $size, $order = null, $lang = null)
55 | {
56 | return $this->client->get('user/simplelist', [
57 | 'department_id' => $departmentId, 'offset' => $offset, 'size' => $size, 'order' => $order, 'lang' => $lang,
58 | ]);
59 | }
60 |
61 | /**
62 | * 获取部门用户详情
63 | *
64 | * @param int $departmentId
65 | * @param int $offset
66 | * @param int $size
67 | * @param string $order
68 | * @param string $lang
69 | *
70 | * @return mixed
71 | */
72 | public function getDetailedUsers($departmentId, $offset, $size, $order = null, $lang = null)
73 | {
74 | return $this->client->get('user/listbypage', [
75 | 'department_id' => $departmentId, 'offset' => $offset, 'size' => $size, 'order' => $order, 'lang' => $lang,
76 | ]);
77 | }
78 |
79 | /**
80 | * 获取管理员列表
81 | *
82 | * @return mixed
83 | */
84 | public function administrators()
85 | {
86 | return $this->client->get('user/get_admin');
87 | }
88 |
89 | /**
90 | * 获取管理员通讯录权限范围
91 | *
92 | * @param string $userid
93 | *
94 | * @return mixed
95 | */
96 | public function administratorScope($userid)
97 | {
98 | return $this->client->get('topapi/user/get_admin_scope', compact('userid'));
99 | }
100 |
101 | /**
102 | * 根据 Unionid 获取 Userid
103 | *
104 | * @param string $unionid
105 | *
106 | * @return mixed
107 | */
108 | public function getUseridByUnionid($unionid)
109 | {
110 | return $this->client->get('user/getUseridByUnionid', compact('unionid'));
111 | }
112 |
113 | /**
114 | * 创建用户
115 | *
116 | * @param array $params
117 | *
118 | * @return mixed
119 | */
120 | public function create(array $params)
121 | {
122 | return $this->client->postJson('user/create', $params);
123 | }
124 |
125 | /**
126 | * 更新用户
127 | *
128 | * @param string $userid
129 | * @param array $params
130 | *
131 | * @return mixed
132 | */
133 | public function update($userid, array $params)
134 | {
135 | return $this->client->postJson('user/update', compact('userid') + $params);
136 | }
137 |
138 | /**
139 | * 删除用户
140 | *
141 | * @param $userid
142 | *
143 | * @return mixed
144 | */
145 | public function delete($userid)
146 | {
147 | return $this->client->get('user/delete', compact('userid'));
148 | }
149 |
150 | /**
151 | * 企业内部应用免登获取用户 Userid
152 | *
153 | * @param string $code
154 | *
155 | * @return mixed
156 | */
157 | public function getUserByCode($code)
158 | {
159 | return $this->client->get('user/getuserinfo', compact('code'));
160 | }
161 |
162 | /**
163 | * 批量增加员工角色
164 | *
165 | * @param array|string $userIds
166 | * @param array|string $roleIds
167 | *
168 | * @return mixed
169 | */
170 | public function addRoles($userIds, $roleIds)
171 | {
172 | $userIds = is_array($userIds) ? implode(',', $userIds) : $userIds;
173 | $roleIds = is_array($roleIds) ? implode(',', $roleIds) : $roleIds;
174 |
175 | return $this->client->postJson('topapi/role/addrolesforemps', compact('userIds', 'roleIds'));
176 | }
177 |
178 | /**
179 | * 批量删除员工角色
180 | *
181 | * @param array|string $userIds
182 | * @param array|string $roleIds
183 | *
184 | * @return mixed
185 | */
186 | public function removeRoles($userIds, $roleIds)
187 | {
188 | $userIds = is_array($userIds) ? implode(',', $userIds) : $userIds;
189 | $roleIds = is_array($roleIds) ? implode(',', $roleIds) : $roleIds;
190 |
191 | return $this->client->postJson('topapi/role/removerolesforemps', compact('userIds', 'roleIds'));
192 | }
193 |
194 | /**
195 | * 获取企业员工人数
196 | *
197 | * @param int $onlyActive
198 | *
199 | * @return mixed
200 | */
201 | public function getCount($onlyActive = 0)
202 | {
203 | return $this->client->get('user/get_org_user_count', compact('onlyActive'));
204 | }
205 |
206 | /**
207 | * 获取企业已激活的员工人数
208 | *
209 | * @return mixed
210 | */
211 | public function getActivatedCount()
212 | {
213 | return $this->getCount(1);
214 | }
215 |
216 | /**
217 | * 根据员工手机号获取 Userid
218 | *
219 | * @param string $mobile
220 | *
221 | * @return mixed
222 | */
223 | public function getUserIdByPhone($mobile = '')
224 | {
225 | return $this->client->get('user/get_by_mobile', compact('mobile'));
226 | }
227 |
228 | /**
229 | * 未登录钉钉的员工列表
230 | *
231 | * @param string $query_date
232 | * @param int $offset
233 | * @param int $size
234 | *
235 | * @return mixed
236 | */
237 | public function getInactiveUsers($query_date, $offset, $size)
238 | {
239 | return $this->client->postJson('topapi/inactive/user/get', [
240 | 'query_date' => $query_date, 'offset' => $offset, 'size' => $size
241 | ]);
242 | }
243 | }
244 |
--------------------------------------------------------------------------------
/src/User/ServiceProvider.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\User;
13 |
14 | use Pimple\Container;
15 | use Pimple\ServiceProviderInterface;
16 |
17 | class ServiceProvider implements ServiceProviderInterface
18 | {
19 | /**
20 | * Registers services on the given container.
21 | * This method should only be used to configure services and parameters.
22 | * It should not get services.
23 | *
24 | * @param \Pimple\Container $pimple A container instance
25 | */
26 | public function register(Container $pimple)
27 | {
28 | $pimple['user'] = function ($app) {
29 | return new Client($app);
30 | };
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/helpers.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk;
13 |
14 | /**
15 | * @param mixed $value
16 | * @param callable $callback
17 | *
18 | * @return mixed
19 | */
20 | function tap($value, $callback)
21 | {
22 | $callback($value);
23 |
24 | return $value;
25 | }
26 |
27 | /**
28 | * Generate a more truly "random" alpha-numeric string.
29 | *
30 | * @param int $length
31 | *
32 | * @return string
33 | */
34 | function str_random($length = 16)
35 | {
36 | $string = '';
37 |
38 | while (($len = strlen($string)) < $length) {
39 | $size = $length - $len;
40 | $bytes = random_bytes($size);
41 | $string .= substr(str_replace(['/', '+', '='], '', base64_encode($bytes)), 0, $size);
42 | }
43 |
44 | return $string;
45 | }
46 |
--------------------------------------------------------------------------------
/tests/ApplicationTest.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Tests;
13 |
14 | use EasyDingTalk\Application;
15 |
16 | class ApplicationTest extends TestCase
17 | {
18 | /** @test */
19 | public function services()
20 | {
21 | $app = new Application();
22 |
23 | $services = [
24 | 'logger' => \Monolog\Logger::class,
25 | 'chat' => \EasyDingTalk\Chat\Client::class,
26 | 'user' => \EasyDingTalk\User\Client::class,
27 | 'role' => \EasyDingTalk\Role\Client::class,
28 | 'media' => \EasyDingTalk\Media\Client::class,
29 | 'sso' => \EasyDingTalk\Auth\SsoClient::class,
30 | 'server' => \EasyDingTalk\Kernel\Server::class,
31 | 'report' => \EasyDingTalk\Report\Client::class,
32 | 'health' => \EasyDingTalk\Health\Client::class,
33 | 'checkin' => \EasyDingTalk\Checkin\Client::class,
34 | 'contact' => \EasyDingTalk\Contact\Client::class,
35 | 'oauth' => \EasyDingTalk\Auth\OAuthClient::class,
36 | 'process' => \EasyDingTalk\Process\Client::class,
37 | 'callback' => \EasyDingTalk\Callback\Client::class,
38 | 'calendar' => \EasyDingTalk\Calendar\Client::class,
39 | 'schedule' => \EasyDingTalk\Schedule\Client::class,
40 | 'microapp' => \EasyDingTalk\Microapp\Client::class,
41 | 'h5app' => \EasyDingTalk\H5app\Client::class,
42 | 'client' => \EasyDingTalk\Kernel\Http\Client::class,
43 | 'config' => \Overtrue\Http\Support\Collection::class,
44 | 'blackboard' => \EasyDingTalk\Blackboard\Client::class,
45 | 'attendance' => \EasyDingTalk\Attendance\Client::class,
46 | 'department' => \EasyDingTalk\Department\Client::class,
47 | 'access_token' => \EasyDingTalk\Kernel\AccessToken::class,
48 | 'conversation' => \EasyDingTalk\Conversation\Client::class,
49 | 'request' => \Symfony\Component\HttpFoundation\Request::class,
50 | 'encryptor' => \EasyDingTalk\Kernel\Encryption\Encryptor::class,
51 | ];
52 |
53 | $this->assertCount(count($services), $app->keys());
54 | foreach ($services as $name => $service) {
55 | $this->assertInstanceof($service, $app->{$name});
56 | $this->assertInstanceof($service, $app[$name]);
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/tests/Blackboard/ClientTest.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Tests\Blackboard;
13 |
14 | use EasyDingTalk\Blackboard\Client;
15 | use EasyDingTalk\Tests\TestCase;
16 |
17 | class ClientTest extends TestCase
18 | {
19 | /** @test */
20 | public function list()
21 | {
22 | $this->make(Client::class)->list('mingyoung')
23 | ->assertUri('topapi/blackboard/listtopten')->assertPostJson(['userid' => 'mingyoung']);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/tests/Calendar/ClientTest.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Tests\Calendar;
13 |
14 | use EasyDingTalk\Calendar\Client;
15 | use EasyDingTalk\Tests\TestCase;
16 |
17 | class ClientTest extends TestCase
18 | {
19 | /** @test */
20 | public function create()
21 | {
22 | $this->make(Client::class)->create($expected = ['foo' => 'bar'])
23 | ->assertUri('topapi/calendar/create')->assertPostJson($expected);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/tests/Callback/ClientTest.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Tests\Callback;
13 |
14 | use EasyDingTalk\Callback\Client;
15 | use EasyDingTalk\Tests\TestCase;
16 |
17 | class ClientTest extends TestCase
18 | {
19 | /** @test */
20 | public function register()
21 | {
22 | $this->make(Client::class)->register($params = ['call_back_tag' => ['foo', 'bar']])
23 | ->assertPostUri('call_back/register_call_back')->assertPostJson(array_merge($params, ['token' => 'test-token', 'aes_key' => 'test-aes-key']));
24 | }
25 |
26 | /** @test */
27 | public function list()
28 | {
29 | $this->make(Client::class)->list()
30 | ->assertGetUri('call_back/get_call_back');
31 | }
32 |
33 | /** @test */
34 | public function update()
35 | {
36 | $this->make(Client::class)->update($params = ['call_back_tag' => ['foo', 'bar']])
37 | ->assertPostUri('call_back/update_call_back')->assertPostJson(array_merge($params, ['token' => 'test-token', 'aes_key' => 'test-aes-key']));
38 | }
39 |
40 | /** @test */
41 | public function delete()
42 | {
43 | $this->make(Client::class)->delete()
44 | ->assertGetUri('call_back/delete_call_back');
45 | }
46 |
47 | /** @test */
48 | public function failed()
49 | {
50 | $this->make(Client::class)->failed()
51 | ->assertGetUri('call_back/get_call_back_failed_result');
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/tests/Chat/ClientTest.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Tests\Chat;
13 |
14 | use EasyDingTalk\Chat\Client;
15 | use EasyDingTalk\Tests\TestCase;
16 |
17 | class ClientTest extends TestCase
18 | {
19 | /** @test */
20 | public function send()
21 | {
22 | $this->make(Client::class)->send('foobar', ['foo' => 'bar'])
23 | ->assertPostUri('chat/send')->assertPostJson([
24 | 'chatid' => 'foobar',
25 | 'msg' => ['foo' => 'bar'],
26 | ]);
27 | }
28 |
29 | /** @test */
30 | public function result()
31 | {
32 | $this->make(Client::class)->result('message-id', 0, 100)
33 | ->assertGetUri('chat/getReadList')->assertQuery([
34 | 'messageId' => 'message-id',
35 | 'cursor' => 0,
36 | 'size' => 100,
37 | ]);
38 | }
39 |
40 | /** @test */
41 | public function create()
42 | {
43 | $this->make(Client::class)->create($params = ['name' => 'EasyDingTalk', 'owner' => 'mingyoung', 'useridlist' => ['mingyoung', 'member']])
44 | ->assertPostUri('chat/create')->assertPostJson($params);
45 | }
46 |
47 | /** @test */
48 | public function update()
49 | {
50 | $this->make(Client::class)->update('chat-id', $params = ['name' => 'EasyDingTalk', 'owner' => 'mingyoung', 'add_useridlist' => ['member']])
51 | ->assertPostUri('chat/update')->assertPostJson(array_merge(['chatid' => 'chat-id'], $params));
52 | }
53 |
54 | /** @test */
55 | public function get()
56 | {
57 | $this->make(Client::class)->get('chat-id')
58 | ->assertGetUri('chat/get')->assertQuery(['chatid' => 'chat-id']);
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/tests/Contact/ClientTest.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Tests\Contact;
13 |
14 | use EasyDingTalk\Contact\Client;
15 | use EasyDingTalk\Tests\TestCase;
16 |
17 | class ClientTest extends TestCase
18 | {
19 | /** @test */
20 | public function labels()
21 | {
22 | $this->make(Client::class)->labels(0, 20)
23 | ->assertUri('topapi/extcontact/listlabelgroups')->assertPostJson(['offset' => 0, 'size' => 20]);
24 | }
25 |
26 | /** @test */
27 | public function list()
28 | {
29 | $this->make(Client::class)->list(0, 20)
30 | ->assertUri('topapi/extcontact/list')->assertPostJson(['offset' => 0, 'size' => 20]);
31 | }
32 |
33 | /** @test */
34 | public function get()
35 | {
36 | $this->make(Client::class)->get('mingyoung')
37 | ->assertUri('topapi/extcontact/get')->assertPostJson(['user_id' => 'mingyoung']);
38 | }
39 |
40 | /** @test */
41 | public function create()
42 | {
43 | $this->make(Client::class)->create(['name' => 'MINGYOUNG'])
44 | ->assertUri('topapi/extcontact/create')->assertPostJson(['contact' => [
45 | 'name' => 'MINGYOUNG',
46 | ]]);
47 | }
48 |
49 | /** @test */
50 | public function update()
51 | {
52 | $this->make(Client::class)->update(123, ['name' => 'MINGYOUNG'])
53 | ->assertUri('topapi/extcontact/update')->assertPostJson(['contact' => [
54 | 'user_id' => 123, 'name' => 'MINGYOUNG',
55 | ]]);
56 | }
57 |
58 | /** @test */
59 | public function delete()
60 | {
61 | $this->make(Client::class)->delete('mingyoung')
62 | ->assertUri('topapi/extcontact/delete')->assertPostJson(['user_id' => 'mingyoung']);
63 | }
64 |
65 | /** @test */
66 | public function scopes()
67 | {
68 | $this->make(Client::class)->scopes()
69 | ->assertUri('auth/scopes');
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/tests/Conversation/ClientTest.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Tests\Conversation;
13 |
14 | use EasyDingTalk\Conversation\Client;
15 | use EasyDingTalk\Tests\TestCase;
16 |
17 | class ClientTest extends TestCase
18 | {
19 | /** @test */
20 | public function sendGeneralMessage()
21 | {
22 | $this->make(Client::class)->sendGeneralMessage('sender-foo', 'cid-bar', ['foo' => 'bar'])
23 | ->assertPostUri('message/send_to_conversation')
24 | ->assertPostJson([
25 | 'sender' => 'sender-foo', 'cid' => 'cid-bar',
26 | 'msg' => ['foo' => 'bar'],
27 | ]);
28 | }
29 |
30 | /** @test */
31 | public function sendCorporationMessage()
32 | {
33 | $this->make(Client::class)->sendCorporationMessage($params = ['foo' => 'bar'])
34 | ->assertPostUri('topapi/message/corpconversation/asyncsend_v2')
35 | ->assertPostFormParams($params);
36 | }
37 |
38 | /** @test */
39 | public function progress()
40 | {
41 | $this->make(Client::class)->corporationMessage('task-id')->progress()
42 | ->assertPostUri('topapi/message/corpconversation/getsendprogress')
43 | ->assertPostJson(['agent_id' => 'mock-agent', 'task_id' => 'task-id']);
44 | }
45 |
46 | /** @test */
47 | public function result()
48 | {
49 | $this->make(Client::class)->corporationMessage('task-id')->result()
50 | ->assertPostUri('topapi/message/corpconversation/getsendresult')
51 | ->assertPostJson(['agent_id' => 'mock-agent', 'task_id' => 'task-id']);
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/tests/Department/ClientTest.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Tests\Department;
13 |
14 | use EasyDingTalk\Department\Client;
15 | use EasyDingTalk\Tests\TestCase;
16 |
17 | class ClientTest extends TestCase
18 | {
19 | /** @test */
20 | public function getSubDepartmentIds()
21 | {
22 | $this->make(Client::class)->getSubDepartmentIds('test-id')
23 | ->assertUri('department/list_ids')->assertQuery(['id' => 'test-id']);
24 | }
25 |
26 | /** @test */
27 | public function list()
28 | {
29 | $this->make(Client::class)->list()
30 | ->assertUri('department/list')->assertQuery(['id' => null, 'lang' => null, 'fetch_child' => 'false']);
31 | }
32 |
33 | /** @test */
34 | public function get()
35 | {
36 | $this->make(Client::class)->get(1)
37 | ->assertUri('department/get')->assertQuery(['id' => 1, 'lang' => null]);
38 | }
39 |
40 | /** @test */
41 | public function getParentsById()
42 | {
43 | $this->make(Client::class)->getParentsById(1)
44 | ->assertUri('department/list_parent_depts_by_dept')->assertQuery(['id' => 1]);
45 | }
46 |
47 | /** @test */
48 | public function getParentsByUserId()
49 | {
50 | $this->make(Client::class)->getParentsByUserId('mingyoung')
51 | ->assertUri('department/list_parent_depts')->assertQuery(['userId' => 'mingyoung']);
52 | }
53 |
54 | /** @test */
55 | public function create()
56 | {
57 | $this->make(Client::class)->create(['name' => 'EasyDingTalk'])
58 | ->assertUri('department/create')->assertPostJson(['name' => 'EasyDingTalk']);
59 | }
60 |
61 | /** @test */
62 | public function update()
63 | {
64 | $this->make(Client::class)->update(1, ['name' => 'EasyDingTalk'])
65 | ->assertUri('department/update')->assertPostJson(['id' => 1, 'name' => 'EasyDingTalk']);
66 | }
67 |
68 | /** @test */
69 | public function delete()
70 | {
71 | $this->make(Client::class)->delete(1)
72 | ->assertUri('department/delete')->assertQuery(['id' => 1]);
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/tests/Health/ClientTest.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Tests\Health;
13 |
14 | use EasyDingTalk\Health\Client;
15 | use EasyDingTalk\Tests\TestCase;
16 |
17 | class ClientTest extends TestCase
18 | {
19 | /** @test */
20 | public function status()
21 | {
22 | $this->make(Client::class)->status('mingyoung')
23 | ->assertPostUri('topapi/health/stepinfo/getuserstatus')
24 | ->assertPostJson(['userid' => 'mingyoung']);
25 | }
26 |
27 | /** @test */
28 | public function byUser()
29 | {
30 | $this->make(Client::class)->byUser('mingyoung', '20180101,20180102')
31 | ->assertPostUri('topapi/health/stepinfo/list')
32 | ->assertPostJson(['type' => 0, 'object_id' => 'mingyoung', 'stat_dates' => '20180101,20180102']);
33 | }
34 |
35 | /** @test */
36 | public function byDepartment()
37 | {
38 | $this->make(Client::class)->byDepartment('mingyoung', '20180101,20180102')
39 | ->assertPostUri('topapi/health/stepinfo/list')
40 | ->assertPostJson(['type' => 1, 'object_id' => 'mingyoung', 'stat_dates' => '20180101,20180102']);
41 | }
42 |
43 | /** @test */
44 | public function byUsers()
45 | {
46 | $this->make(Client::class)->byUsers(['mingyoung', 'cc'], '20180101')
47 | ->assertPostUri('topapi/health/stepinfo/listbyuserid')
48 | ->assertPostJson(['userids' => 'mingyoung,cc', 'stat_date' => '20180101']);
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/tests/Kernel/Concerns/InteractsWithCacheTest.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Tests\Kernel\Concerns;
13 |
14 | use EasyDingTalk\Kernel\Concerns\InteractsWithCache;
15 | use EasyDingTalk\Tests\TestCase;
16 | use Mockery;
17 | use Psr\SimpleCache\CacheInterface;
18 |
19 | class InteractsWithCacheTest extends TestCase
20 | {
21 | /** @test */
22 | public function getCache()
23 | {
24 | $cache = Mockery::mock(InteractsWithCache::class);
25 |
26 | $this->assertInstanceof(CacheInterface::class, $cache->getCache());
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/tests/Kernel/Encryption/EncryptorTest.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Tests\Kernel\Encryption;
13 |
14 | use EasyDingTalk\Kernel\Encryption\Encryptor;
15 | use EasyDingTalk\Tests\TestCase;
16 |
17 | class EncryptorTest extends TestCase
18 | {
19 | /**
20 | * @return \EasyDingTalk\Kernel\Encryption\Encryptor
21 | */
22 | public function makeEncryptor()
23 | {
24 | return new Encryptor('suite4xxxxxxxxxxxxxxx', '123456', '4g5j64qlyl3zvetqxz5jiocdr586fn2zvjpa8zls3ij');
25 | }
26 |
27 | /** @test */
28 | public function encrypt()
29 | {
30 | $encryptor = $this->makeEncryptor();
31 | $result = json_decode($encryptor->encrypt('{"EventType":"check_create_suite_url","Random":"LPIdSnlF","TestSuiteKey":"suite4xxxxxxxxxxxxxxx"}'), true);
32 |
33 | $result = $encryptor->decrypt(
34 | $result['encrypt'], $result['msg_signature'], $result['nonce'], $result['timeStamp']
35 | );
36 |
37 | $this->assertSameDecryptedData($result);
38 | }
39 |
40 | /** @test */
41 | public function decrypt()
42 | {
43 | $encryptor = $this->makeEncryptor();
44 |
45 | $result = $encryptor->decrypt(
46 | '1a3NBxmCFwkCJvfoQ7WhJHB+iX3qHPsc9JbaDznE1i03peOk1LaOQoRz3+nlyGNhwmwJ3vDMG+OzrHMeiZI7gTRWVdUBmfxjZ8Ej23JVYa9VrYeJ5as7XM/ZpulX8NEQis44w53h1qAgnC3PRzM7Zc/D6Ibr0rgUathB6zRHP8PYrfgnNOS9PhSBdHlegK+AGGanfwjXuQ9+0pZcy0w9lQ==',
47 | '5a65ceeef9aab2d149439f82dc191dd6c5cbe2c0',
48 | 'nEXhMP4r',
49 | '1445827045067'
50 | );
51 |
52 | $this->assertSameDecryptedData($result);
53 | }
54 |
55 | protected function assertSameDecryptedData($result)
56 | {
57 | $this->assertSame('{"EventType":"check_create_suite_url","Random":"LPIdSnlF","TestSuiteKey":"suite4xxxxxxxxxxxxxxx"}', $result);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/tests/Media/ClientTest.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Tests\Media;
13 |
14 | use EasyDingTalk\Media\Client;
15 | use EasyDingTalk\Tests\TestCase;
16 |
17 | class ClientTest extends TestCase
18 | {
19 | /** @test */
20 | public function uploadImage()
21 | {
22 | $this->make(Client::class)->uploadImage(__DIR__.'/__fixtures__/foo.stub')
23 | ->assertPostUri('media/upload');
24 | }
25 |
26 | /** @test */
27 | public function uploadVoice()
28 | {
29 | $this->make(Client::class)->uploadVoice(__DIR__.'/__fixtures__/foo.stub')
30 | ->assertPostUri('media/upload');
31 | }
32 |
33 | /** @test */
34 | public function uploadFile()
35 | {
36 | $this->make(Client::class)->uploadFile(__DIR__.'/__fixtures__/foo.stub')
37 | ->assertPostUri('media/upload');
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/tests/Media/__fixtures__/foo.stub:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mingyoung/dingtalk/f00500f40514015429b18bc9178c7270a1d7dea9/tests/Media/__fixtures__/foo.stub
--------------------------------------------------------------------------------
/tests/Messages/FileTest.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Tests\Messages;
13 |
14 | use EasyDingTalk\Messages\File;
15 | use EasyDingTalk\Tests\TestCase;
16 |
17 | class FileTest extends TestCase
18 | {
19 | /** @test */
20 | public function staticMake()
21 | {
22 | $message = File::make('media-id');
23 | $expected = [
24 | 'msgtype' => 'file',
25 | 'file' => [
26 | 'media_id' => 'media-id',
27 | ],
28 | ];
29 |
30 | $this->assertSame($expected, $message->toArray());
31 | $this->assertSame(json_encode($expected), $message->toJson());
32 | }
33 |
34 | /** @test */
35 | public function new()
36 | {
37 | $message = new File('media-id');
38 | $expected = [
39 | 'msgtype' => 'file',
40 | 'file' => [
41 | 'media_id' => 'media-id',
42 | ],
43 | ];
44 |
45 | $this->assertSame($expected, $message->toArray());
46 | $this->assertSame(json_encode($expected), $message->toJson());
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/tests/Messages/ImageTest.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Tests\Messages;
13 |
14 | use EasyDingTalk\Messages\Image;
15 | use EasyDingTalk\Tests\TestCase;
16 |
17 | class ImageTest extends TestCase
18 | {
19 | /** @test */
20 | public function staticMake()
21 | {
22 | $message = Image::make('media-id');
23 | $expected = [
24 | 'msgtype' => 'image',
25 | 'image' => [
26 | 'media_id' => 'media-id',
27 | ],
28 | ];
29 |
30 | $this->assertSame($expected, $message->toArray());
31 | $this->assertSame(json_encode($expected), $message->toJson());
32 | }
33 |
34 | /** @test */
35 | public function new()
36 | {
37 | $message = new Image('media-id');
38 |
39 | $expected = [
40 | 'msgtype' => 'image',
41 | 'image' => [
42 | 'media_id' => 'media-id',
43 | ],
44 | ];
45 |
46 | $this->assertSame($expected, $message->toArray());
47 | $this->assertSame(json_encode($expected), $message->toJson());
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/tests/Messages/LinkTest.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Tests\Messages;
13 |
14 | use EasyDingTalk\Messages\Link;
15 | use EasyDingTalk\Tests\TestCase;
16 |
17 | class LinkTest extends TestCase
18 | {
19 | /** @test */
20 | public function staticMake()
21 | {
22 | $message = Link::make('https://example.com')->setPictureUrl('@lALOACZwe2Rk')->setTitle('测试')->setText('测试');
23 | $expected = [
24 | 'msgtype' => 'link',
25 | 'link' => [
26 | 'messageUrl' => 'https://example.com',
27 | 'picUrl' => '@lALOACZwe2Rk',
28 | 'title' => '测试',
29 | 'text' => '测试',
30 | ],
31 | ];
32 |
33 | $this->assertSame($expected, $message->toArray());
34 | $this->assertSame(json_encode($expected), $message->toJson());
35 | }
36 |
37 | /** @test */
38 | public function new()
39 | {
40 | $message = (new Link('https://example.com'))->setPictureUrl('@lALOACZwe2Rk')->setTitle('测试')->setText('测试');
41 | $expected = [
42 | 'msgtype' => 'link',
43 | 'link' => [
44 | 'messageUrl' => 'https://example.com',
45 | 'picUrl' => '@lALOACZwe2Rk',
46 | 'title' => '测试',
47 | 'text' => '测试',
48 | ],
49 | ];
50 |
51 | $this->assertSame($expected, $message->toArray());
52 | $this->assertSame(json_encode($expected), $message->toJson());
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/tests/Messages/TextTest.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Tests\Messages;
13 |
14 | use EasyDingTalk\Messages\Text;
15 | use EasyDingTalk\Tests\TestCase;
16 |
17 | class TextTest extends TestCase
18 | {
19 | /** @test */
20 | public function staticMake()
21 | {
22 | $message = Text::make('mock');
23 | $expected = [
24 | 'msgtype' => 'text',
25 | 'text' => [
26 | 'content' => 'mock',
27 | ],
28 | ];
29 |
30 | $this->assertSame($expected, $message->toArray());
31 | $this->assertSame(json_encode($expected), $message->toJson());
32 | }
33 |
34 | /** @test */
35 | public function new()
36 | {
37 | $message = new Text('mock');
38 | $expected = [
39 | 'msgtype' => 'text',
40 | 'text' => [
41 | 'content' => 'mock',
42 | ],
43 | ];
44 |
45 | $this->assertSame($expected, $message->toArray());
46 | $this->assertSame(json_encode($expected), $message->toJson());
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/tests/Messages/VoiceTest.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Tests\Messages;
13 |
14 | use EasyDingTalk\Messages\Voice;
15 | use EasyDingTalk\Tests\TestCase;
16 |
17 | class VoiceTest extends TestCase
18 | {
19 | /** @test */
20 | public function staticMake()
21 | {
22 | $message = Voice::make('media-id', 10);
23 | $expected = [
24 | 'msgtype' => 'voice',
25 | 'voice' => [
26 | 'media_id' => 'media-id',
27 | 'duration' => 10,
28 | ],
29 | ];
30 |
31 | $this->assertSame($expected, $message->toArray());
32 | $this->assertSame(json_encode($expected), $message->toJson());
33 | }
34 |
35 | /** @test */
36 | public function new()
37 | {
38 | $message = new Voice('media-id', 10);
39 |
40 | $expected = [
41 | 'msgtype' => 'voice',
42 | 'voice' => [
43 | 'media_id' => 'media-id',
44 | 'duration' => 10,
45 | ],
46 | ];
47 |
48 | $this->assertSame($expected, $message->toArray());
49 | $this->assertSame(json_encode($expected), $message->toJson());
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/tests/Microapp/ClientTest.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Tests\Microapp;
13 |
14 | use EasyDingTalk\Microapp\Client;
15 | use EasyDingTalk\Tests\TestCase;
16 |
17 | class ClientTest extends TestCase
18 | {
19 | /** @test */
20 | public function list()
21 | {
22 | $this->make(Client::class)->list()
23 | ->assertUri('microapp/list')->assertEmptyQuery();
24 | }
25 |
26 | /** @test */
27 | public function listByUserId()
28 | {
29 | $this->make(Client::class)->listByUserId('mingyoung')
30 | ->assertUri('microapp/list_by_userid')->assertQuery(['userid' => 'mingyoung']);
31 | }
32 |
33 | /** @test */
34 | public function getVisibility()
35 | {
36 | $this->make(Client::class)->getVisibility('123')
37 | ->assertUri('microapp/visible_scopes')->assertPostJson(['agentId' => '123']);
38 | }
39 |
40 | /** @test */
41 | public function setVisibility()
42 | {
43 | $this->make(Client::class)->setVisibility([
44 | 'agentId' => 123456,
45 | 'isHidden' => false,
46 | 'deptVisibleScopes' => [1, 2],
47 | 'userVisibleScopes' => ['user1', 'user2'],
48 | ])->assertUri('microapp/set_visible_scopes')->assertPostJson([
49 | 'agentId' => 123456,
50 | 'isHidden' => false,
51 | 'deptVisibleScopes' => [1, 2],
52 | 'userVisibleScopes' => ['user1', 'user2'],
53 | ]);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/tests/Report/ClientTest.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Tests\Report;
13 |
14 | use EasyDingTalk\Report\Client;
15 | use EasyDingTalk\Tests\TestCase;
16 |
17 | class ClientTest extends TestCase
18 | {
19 | /** @test */
20 | public function list()
21 | {
22 | $expected = [
23 | 'start_time' => 1507564800000,
24 | 'end_time' => 1507564800000,
25 | 'userid' => 'mingyoung',
26 | ];
27 |
28 | $this->make(Client::class)->list($expected)
29 | ->assertUri('topapi/report/list')->assertPostJson($expected);
30 | }
31 |
32 | /** @test */
33 | public function templates()
34 | {
35 | $expected = [
36 | 'userid' => 'mingyoung',
37 | 'offset' => 100,
38 | 'size' => 50,
39 | ];
40 |
41 | $this->make(Client::class)->templates('mingyoung', 100, 50)
42 | ->assertUri('topapi/report/template/listbyuserid')->assertPostJson($expected);
43 | }
44 |
45 | /** @test */
46 | public function unreadCount()
47 | {
48 | $this->make(Client::class)->unreadCount('mingyoung')
49 | ->assertUri('topapi/report/getunreadcount')->assertPostJson(['userid' => 'mingyoung']);
50 | }
51 |
52 | /** @test */
53 | public function statistics()
54 | {
55 | $this->make(Client::class)->statistics('xxxxxxx')
56 | ->assertUri('topapi/report/statistics')->assertPostJson(['report_id' => 'xxxxxxx']);
57 | }
58 |
59 | /** @test */
60 | public function statisticsByType()
61 | {
62 | $this->make(Client::class)->statisticsByType('xxxxxxx',0)
63 | ->assertUri('topapi/report/statistics/listbytype')->assertPostJson([
64 | 'report_id' => 'xxxxxxx', 'type' => 0, 'offset' => 0, 'size' => 100,
65 | ]);
66 | }
67 |
68 | /** @test */
69 | public function getReceivers()
70 | {
71 | $this->make(Client::class)->getReceivers('xxxxxxx')
72 | ->assertUri('topapi/report/receiver/list')->assertPostJson([
73 | 'report_id' => 'xxxxxxx', 'offset' => 0, 'size' => 100,
74 | ]);
75 | }
76 |
77 | /** @test */
78 | public function getComments()
79 | {
80 | $this->make(Client::class)->getComments('mingyoung')
81 | ->assertUri('topapi/report/comment/list')->assertPostJson([
82 | 'report_id' => 'mingyoung', 'offset' => 0, 'size' => 100,
83 | ]);
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/tests/Role/ClientTest.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Tests\Role;
13 |
14 | use EasyDingTalk\Role\Client;
15 | use EasyDingTalk\Tests\TestCase;
16 |
17 | class ClientTest extends TestCase
18 | {
19 | /** @test */
20 | public function list()
21 | {
22 | $this->make(Client::class)->list()
23 | ->assertUri('topapi/role/list')->assertPostJson(['offset' => null, 'size' => null]);
24 | }
25 |
26 | /** @test */
27 | public function getUsers()
28 | {
29 | $this->make(Client::class)->getUsers(123)
30 | ->assertUri('topapi/role/simplelist')->assertPostJson(['offset' => null, 'size' => null, 'role_id' => 123]);
31 | }
32 |
33 | /** @test */
34 | public function getRoleGroups()
35 | {
36 | $this->make(Client::class)->getGroups(123)
37 | ->assertUri('topapi/role/getrolegroup')->assertPostJson(['group_id' => 123]);
38 | }
39 |
40 | /** @test */
41 | public function get()
42 | {
43 | $this->make(Client::class)->get(123)
44 | ->assertUri('topapi/role/getrole')->assertPostJson(['roleId' => 123]);
45 | }
46 |
47 | /** @test */
48 | public function create()
49 | {
50 | $this->make(Client::class)->create(123, 'Admin')
51 | ->assertUri('role/add_role')->assertPostJson(['groupId' => 123, 'roleName' => 'Admin']);
52 | }
53 |
54 | /** @test */
55 | public function update()
56 | {
57 | $this->make(Client::class)->update(123, 'Admin')
58 | ->assertUri('role/update_role')->assertPostJson(['roleId' => 123, 'roleName' => 'Admin']);
59 | }
60 |
61 | /** @test */
62 | public function delete()
63 | {
64 | $this->make(Client::class)->delete(123)
65 | ->assertUri('topapi/role/deleterole')->assertPostJson(['role_id' => 123]);
66 | }
67 |
68 | /** @test */
69 | public function createGroup()
70 | {
71 | $this->make(Client::class)->createGroup('Group')
72 | ->assertUri('role/add_role_group')->assertPostJson(['name' => 'Group']);
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/tests/Schedule/ClientTest.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Tests\Schedule;
13 |
14 | use EasyDingTalk\Schedule\Client;
15 | use EasyDingTalk\Tests\TestCase;
16 |
17 | class ClientTest extends TestCase
18 | {
19 | /** @test */
20 | public function add()
21 | {
22 | $this->make(Client::class)->add($params = [
23 | 'userid' => 'mingyoung',
24 | 'create_time' => 1496678400000,
25 | 'title' => '标题',
26 | 'url' => 'https://easydingtalk.org',
27 | 'formItemList' => [
28 | [
29 | 'title' => '标题',
30 | 'content' => '内容',
31 | ],
32 | ],
33 | ])
34 | ->assertUri('topapi/workrecord/add')
35 | ->assertPostJson($params);
36 | }
37 |
38 | /** @test */
39 | public function update()
40 | {
41 | $this->make(Client::class)->update('mingyoung', 'record123')
42 | ->assertUri('topapi/workrecord/update')
43 | ->assertPostJson(['userid' => 'mingyoung', 'record_id' => 'record123']);
44 | }
45 |
46 | /** @test */
47 | public function completedList()
48 | {
49 | $this->make(Client::class)->list('mingyoung', true, 0, 50)
50 | ->assertUri('topapi/workrecord/getbyuserid')
51 | ->assertPostJson([
52 | 'userid' => 'mingyoung',
53 | 'status' => 1,
54 | 'offset' => 0,
55 | 'limit' => 50,
56 | ]);
57 | }
58 |
59 | /** @test */
60 | public function incompletedList()
61 | {
62 | $this->make(Client::class)->list('mingyoung', false, 0, 50)
63 | ->assertUri('topapi/workrecord/getbyuserid')
64 | ->assertPostJson([
65 | 'userid' => 'mingyoung',
66 | 'status' => 0,
67 | 'offset' => 0,
68 | 'limit' => 50,
69 | ]);
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/tests/TestCase.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Tests;
13 |
14 | use EasyDingTalk\Application;
15 | use GuzzleHttp\ClientInterface;
16 | use Mockery;
17 | use PHPUnit\Framework\TestCase as BaseTestCase;
18 |
19 | class TestCase extends BaseTestCase
20 | {
21 | /**
22 | * @param \EasyDingTalk\Kernel\BaseClient $client
23 | *
24 | * @return \EasyDingTalk\Kernel\BaseClient
25 | */
26 | protected function make($client)
27 | {
28 | $app = $this->newApplication([
29 | 'token' => 'test-token',
30 | 'aes_key' => 'test-aes-key',
31 | 'http' => ['response_type' => 'raw'],
32 | ]);
33 |
34 | $response = new TestResponse(200, [], '{"mock": "test"}');
35 |
36 | $app['client']->setHttpClient(Mockery::mock(ClientInterface::class, function ($mock) use ($response) {
37 | $mock->shouldReceive('request')->withArgs($response->setExpectedArguments())->andReturn($response);
38 | }));
39 |
40 | return new $client($app);
41 | }
42 |
43 | /**
44 | * @param array $config
45 | * @param array $overrides
46 | *
47 | * @return \EasyDingTalk\Application
48 | */
49 | protected function newApplication(array $config = [], array $overrides = [])
50 | {
51 | return new Application(array_merge(['appkey' => 'mock-appkey', 'appsecret' => 'mock-appsecret', 'agent_id' => 'mock-agent'], $config), $overrides);
52 | }
53 |
54 | protected function tearDown()
55 | {
56 | Mockery::close();
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/tests/TestResponse.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Tests;
13 |
14 | use GuzzleHttp\Psr7\Response;
15 | use PHPUnit\Framework\Assert;
16 |
17 | class TestResponse extends Response
18 | {
19 | /**
20 | * @var string
21 | */
22 | protected $method;
23 |
24 | /**
25 | * @var string
26 | */
27 | protected $uri;
28 |
29 | /**
30 | * @var array
31 | */
32 | protected $options;
33 |
34 | /**
35 | * Request arguments.
36 | *
37 | * @return \Closure
38 | */
39 | public function setExpectedArguments()
40 | {
41 | return function () {
42 | list($this->method, $this->uri, $this->options) = func_get_args();
43 |
44 | return true;
45 | };
46 | }
47 |
48 | /**
49 | * @throws \PHPUnit\Framework\ExpectationFailedException
50 | *
51 | * @param string $method
52 | *
53 | * @return $this
54 | */
55 | public function assertMethod($method)
56 | {
57 | Assert::assertSame($this->method, $method);
58 |
59 | return $this;
60 | }
61 |
62 | /**
63 | * @throws \PHPUnit\Framework\ExpectationFailedException
64 | *
65 | * @param string $uri
66 | *
67 | * @return $this
68 | */
69 | public function assertUri($uri)
70 | {
71 | Assert::assertSame($this->uri, $uri);
72 |
73 | return $this;
74 | }
75 |
76 | /**
77 | * @throws \PHPUnit\Framework\ExpectationFailedException
78 | *
79 | * @param string $uri
80 | *
81 | * @return $this
82 | */
83 | public function assertGetUri($uri)
84 | {
85 | return $this->assertMethod('GET')->assertUri($uri);
86 | }
87 |
88 | /**
89 | * @throws \PHPUnit\Framework\ExpectationFailedException
90 | *
91 | * @param string $uri
92 | *
93 | * @return $this
94 | */
95 | public function assertPostUri($uri)
96 | {
97 | return $this->assertMethod('POST')->assertUri($uri);
98 | }
99 |
100 | /**
101 | * @throws \PHPUnit\Framework\ExpectationFailedException
102 | *
103 | * @param array $query
104 | *
105 | * @return $this
106 | */
107 | public function assertQuery($query)
108 | {
109 | Assert::assertSame($this->options['query'], $query);
110 |
111 | return $this;
112 | }
113 |
114 | /**
115 | * @throws \PHPUnit\Framework\ExpectationFailedException
116 | *
117 | * @return $this
118 | */
119 | public function assertEmptyQuery()
120 | {
121 | return $this->assertQuery([]);
122 | }
123 |
124 | /**
125 | * @throws \PHPUnit\Framework\ExpectationFailedException
126 | *
127 | * @param array $json
128 | *
129 | * @return $this
130 | */
131 | public function assertPostJson($json)
132 | {
133 | Assert::assertSame($this->options['json'], $json);
134 |
135 | return $this;
136 | }
137 |
138 | /**
139 | * @param array $params
140 | *
141 | * @return $this
142 | */
143 | public function assertPostFormParams($params)
144 | {
145 | Assert::assertSame($this->options['form_params'], $params);
146 |
147 | return $this;
148 | }
149 | }
150 |
--------------------------------------------------------------------------------
/tests/User/ClientTest.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace EasyDingTalk\Tests\User;
13 |
14 | use EasyDingTalk\Tests\TestCase;
15 | use EasyDingTalk\User\Client;
16 |
17 | class ClientTest extends TestCase
18 | {
19 | /** @test */
20 | public function get()
21 | {
22 | $this->make(Client::class)->get('mingyoung')
23 | ->assertUri('user/get')->assertQuery(['userid' => 'mingyoung', 'lang' => null]);
24 |
25 | $this->make(Client::class)->get('mingyoung', 'zh-CN')
26 | ->assertUri('user/get')->assertQuery(['userid' => 'mingyoung', 'lang' => 'zh-CN']);
27 | }
28 |
29 | /** @test */
30 | public function getUserIds()
31 | {
32 | $this->make(Client::class)->getUserIds('123')
33 | ->assertUri('user/getDeptMember')->assertQuery(['deptId' => '123']);
34 | }
35 |
36 | /** @test */
37 | public function getUsers()
38 | {
39 | $this->make(Client::class)->getUsers('123', 10, 20)
40 | ->assertUri('user/simplelist')->assertQuery(['department_id' => '123', 'offset' => 10, 'size' => 20, 'order' => null, 'lang' => null]);
41 | }
42 |
43 | /** @test */
44 | public function getDetailedUsers()
45 | {
46 | $this->make(Client::class)->getDetailedUsers('123', 10, 20)
47 | ->assertUri('user/listbypage')->assertQuery(['department_id' => '123', 'offset' => 10, 'size' => 20, 'order' => null, 'lang' => null]);
48 | }
49 |
50 | /** @test */
51 | public function administrators()
52 | {
53 | $this->make(Client::class)->administrators()
54 | ->assertUri('user/get_admin');
55 | }
56 |
57 | /** @test */
58 | public function administratorScope()
59 | {
60 | $this->make(Client::class)->administratorScope('mingyoung')
61 | ->assertUri('topapi/user/get_admin_scope')->assertQuery(['userid' => 'mingyoung']);
62 | }
63 |
64 | /** @test */
65 | public function getUseridByUnionid()
66 | {
67 | $this->make(Client::class)->getUseridByUnionid('mingyoung')
68 | ->assertUri('user/getUseridByUnionid')->assertQuery(['unionid' => 'mingyoung']);
69 | }
70 |
71 | /** @test */
72 | public function create()
73 | {
74 | $this->make(Client::class)->create(['userid' => 'mingyoung', 'name' => 'MINGYOUNG'])
75 | ->assertUri('user/create')->assertPostJson([
76 | 'userid' => 'mingyoung', 'name' => 'MINGYOUNG',
77 | ]);
78 | }
79 |
80 | /** @test */
81 | public function update()
82 | {
83 | $this->make(Client::class)->update('mingyoung', ['name' => 'MINGYOUNG'])
84 | ->assertUri('user/update')->assertPostJson([
85 | 'userid' => 'mingyoung',
86 | 'name' => 'MINGYOUNG',
87 | ]);
88 | }
89 |
90 | /** @test */
91 | public function delete()
92 | {
93 | $this->make(Client::class)->delete('mingyoung')
94 | ->assertUri('user/delete')->assertQuery(['userid' => 'mingyoung']);
95 | }
96 |
97 | /** @test */
98 | public function getUserByCode()
99 | {
100 | $this->make(Client::class)->getUserByCode('code')
101 | ->assertUri('user/getuserinfo')->assertQuery(['code' => 'code']);
102 | }
103 |
104 | /** @test */
105 | public function addRoles()
106 | {
107 | $this->make(Client::class)->addRoles('user1,user2', 'role1,role2')
108 | ->assertUri('topapi/role/addrolesforemps')->assertPostJson(['userIds' => 'user1,user2', 'roleIds' => 'role1,role2']);
109 |
110 | $this->make(Client::class)->addRoles(['user1', 'user2'], ['role1', 'role2'])
111 | ->assertUri('topapi/role/addrolesforemps')->assertPostJson(['userIds' => 'user1,user2', 'roleIds' => 'role1,role2']);
112 | }
113 |
114 | /** @test */
115 | public function removeRoles()
116 | {
117 | $this->make(Client::class)->removeRoles('user1,user2', 'role1,role2')
118 | ->assertUri('topapi/role/removerolesforemps')->assertPostJson(['userIds' => 'user1,user2', 'roleIds' => 'role1,role2']);
119 |
120 | $this->make(Client::class)->removeRoles(['user1', 'user2'], ['role1', 'role2'])
121 | ->assertUri('topapi/role/removerolesforemps')->assertPostJson(['userIds' => 'user1,user2', 'roleIds' => 'role1,role2']);
122 | }
123 |
124 | /** @test */
125 | public function getUserCount()
126 | {
127 | $this->make(Client::class)->getCount()
128 | ->assertUri('user/get_org_user_count')->assertQuery(['onlyActive' => 0]);
129 | }
130 |
131 | /** @test */
132 | public function getActivatedCount()
133 | {
134 | $this->make(Client::class)->getActivatedCount()
135 | ->assertUri('user/get_org_user_count')->assertQuery(['onlyActive' => 1]);
136 | }
137 |
138 | /** @test */
139 | public function getUserIdByPhone()
140 | {
141 | $this->make(Client::class)->getUserIdByPhone('18888888888')
142 | ->assertUri('user/get_by_mobile')->assertQuery(['mobile' => '18888888888']);
143 | }
144 |
145 | /** @test */
146 | public function getInactiveUsers()
147 | {
148 | $this->make(Client::class)->getInactiveUsers('20190808',0,100)
149 | ->assertUri('topapi/inactive/user/get')->assertPostJson(['query_date' => '20190808', 'offset' => 0, 'size' => 100]);
150 | }
151 | }
152 |
--------------------------------------------------------------------------------