初始版本
This commit is contained in:
commit
09f050888e
|
@ -0,0 +1,4 @@
|
|||
.idea
|
||||
/vendor
|
||||
.php_cs.cache
|
||||
composer.lock
|
|
@ -0,0 +1,16 @@
|
|||
language: php
|
||||
|
||||
php:
|
||||
- 7.0
|
||||
- 7.1
|
||||
- 7.2
|
||||
|
||||
dist: trusty
|
||||
sudo: false
|
||||
|
||||
before_script:
|
||||
- composer self-update
|
||||
- composer install --prefer-source --no-interaction
|
||||
- composer dump-autoload
|
||||
|
||||
script: vendor/bin/phpunit
|
|
@ -0,0 +1,226 @@
|
|||
# 钉钉推送机器人消息发送laravel扩展包
|
||||
|
||||
[![Latest Stable Version](https://poser.pugx.org/wangju/ding-notice/v/stable)](https://packagist.org/packages/wangju/ding-notice)
|
||||
[![Total Downloads](https://poser.pugx.org/wangju/ding-notice/downloads)](https://packagist.org/packages/wangju/ding-notice)
|
||||
[![Latest Unstable Version](https://poser.pugx.org/wangju/ding-notice/v/unstable)](https://packagist.org/packages/wangju/ding-notice)
|
||||
[![License](https://poser.pugx.org/wangju/ding-notice/license)](https://packagist.org/packages/wangju/ding-notice)
|
||||
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/wowiwj/ding-notice/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/wowiwj/ding-notice/?branch=master)
|
||||
[![Code Intelligence Status](https://scrutinizer-ci.com/g/wowiwj/ding-notice/badges/code-intelligence.svg?b=master)](https://scrutinizer-ci.com/code-intelligence)
|
||||
[![Open Source Love](https://badges.frapsoft.com/os/v1/open-source.svg?v=103)](https://github.com/ellerbrock/open-source-badge/)
|
||||
|
||||
|
||||
### 请先阅读 [钉钉官方文档](https://open-doc.dingtalk.com/microapp/serverapi2/qf2nxq)
|
||||
|
||||
|
||||
# 介绍
|
||||
ding-notie 是一款钉钉机器人消息发送的Laravel扩展,您可以通过此扩展便捷的发送钉钉消息,进行监控和提醒操作
|
||||
|
||||
# 要求
|
||||
- php版本:>=7.0
|
||||
- laravel版本: Laravel5.5+
|
||||
|
||||
|
||||
# 安装
|
||||
|
||||
```php
|
||||
composer require ykxiao/dm-ding-notice
|
||||
|
||||
```
|
||||
|
||||
# 在非laravel项目中使用
|
||||
```php
|
||||
$ding = new \DingNotice\DingTalk([
|
||||
"default" => [
|
||||
'enabled' => true,
|
||||
'token' => "you-push-token",
|
||||
'timeout' => 2.0,
|
||||
'ssl_verify' => true,
|
||||
'secret' => '',
|
||||
]
|
||||
]);
|
||||
|
||||
$ding->text('我就是我, xxx 是不一样的烟火');
|
||||
```
|
||||
|
||||
# 在laravel项目中使用
|
||||
|
||||
安装成功后执行
|
||||
```php
|
||||
php artisan vendor:publish --provider="DingNotice\DingNoticeServiceProvider"
|
||||
|
||||
```
|
||||
会自动将`ding.php`添加到您项目的配置文件当中
|
||||
|
||||
# 相关配置
|
||||
|
||||
### 钉钉启用开关
|
||||
(可选)默认为开启
|
||||
```php
|
||||
DING_ENABLED=true
|
||||
```
|
||||
### 钉钉的推送token
|
||||
- (必选)发送钉钉机器人的token,即在您创建机器人之后的access_token
|
||||
- 钉钉推送链接:https://oapi.dingtalk.com/robot/send?access_token=you-push-token
|
||||
```php
|
||||
DING_TOKEN=you-push-token
|
||||
```
|
||||
|
||||
|
||||
### 多机器人配置
|
||||
如果想要添加多个机器人,则在`ding.php`当中添加机器人名字和相关的配置即可
|
||||
|
||||
```php
|
||||
return [
|
||||
|
||||
'default' => [
|
||||
'enabled' => env('DING_ENABLED',true),
|
||||
|
||||
'token' => env('DING_TOKEN',''),
|
||||
|
||||
'timeout' => env('DING_TIME_OUT',2.0),
|
||||
|
||||
'ssl_verify' => env('DING_SSL_VERIFY',true),
|
||||
|
||||
'secret' => env('DING_SECRET',true),
|
||||
],
|
||||
|
||||
'other' => [
|
||||
'enabled' => env('OTHER_DING_ENABLED',true),
|
||||
|
||||
'token' => env('OTHER_DING_TOKEN',''),
|
||||
|
||||
'timeout' => env('OTHER_DING_TIME_OUT',2.0),
|
||||
|
||||
'ssl_verify' => env('DING_SSL_VERIFY',true),
|
||||
|
||||
'secret' => env('OTHER_DING_SECRET',true),
|
||||
]
|
||||
|
||||
];
|
||||
```
|
||||
|
||||
|
||||
### 钉钉发送的超时时间
|
||||
- (可选) 默认为2.0秒
|
||||
```php
|
||||
DING_TIME_OUT=
|
||||
```
|
||||
|
||||
### 是否开启SSL验证
|
||||
|
||||
- (可选)默认为开启,关闭请手动设置
|
||||
```php
|
||||
DING_SSL_VERIFY=false
|
||||
```
|
||||
### 开启钉钉安全配置
|
||||
|
||||
- (可选)默认为无
|
||||
```php
|
||||
DING_SECRET=
|
||||
```
|
||||
|
||||
|
||||
# 使用
|
||||
|
||||
## 发送纯文字消息
|
||||
```php
|
||||
ding('我就是我, xxx 是不一样的烟火')
|
||||
```
|
||||
or
|
||||
```php
|
||||
ding()->text('我就是我, xxx 是不一样的烟火')
|
||||
```
|
||||
发送过程@其他人或者所有人
|
||||
|
||||
```php
|
||||
ding()->at(["13888888888"],true)
|
||||
->text("我就是我,@13888888888 是不一样的烟火")
|
||||
```
|
||||
|
||||
## 发送链接类型的消息
|
||||
|
||||
|
||||
```php
|
||||
|
||||
$title = "自定义机器人协议";
|
||||
$text = "群机器人是钉钉群的高级扩展功能。群机器人可以将第三方服务的信息聚合到群聊中,实现自动化的信息同步。例如:通过聚合GitHub,GitLab等源码管理服务,实现源码更新同步;通过聚合Trello,JIRA等项目协调服务,实现项目信息同步。不仅如此,群机器人支持Webhook协议的自定义接入,支持更多可能性,例如:你可将运维报警提醒通过自定义机器人聚合到钉钉群。";
|
||||
$picUrl = "";
|
||||
$messageUrl = "https://open-doc.dingtalk.com/docs/doc.htm?spm=a219a.7629140.0.0.Rqyvqo&treeId=257&articleId=105735&docType=1";
|
||||
|
||||
ding()->link($title,$text,$messageUrl,$picUrl)
|
||||
```
|
||||
|
||||
## 发送markdown类型的消息
|
||||
|
||||
```php
|
||||
$title = '杭州天气';
|
||||
$markdown = "#### 杭州天气 \n ".
|
||||
"> 9度,@1825718XXXX 西北风1级,空气良89,相对温度73%\n\n ".
|
||||
"> ![screenshot](http://i01.lw.aliimg.com/media/lALPBbCc1ZhJGIvNAkzNBLA_1200_588.png)\n".
|
||||
"> ###### 10点20分发布 [天气](http://www.thinkpage.cn/) ";
|
||||
|
||||
ding()->markdown($title,$markdown);
|
||||
```
|
||||
or
|
||||
|
||||
```php
|
||||
ding()->at([],true)
|
||||
->markdown($title,$markdown)
|
||||
```
|
||||
|
||||
## 发送Action类型的消息
|
||||
|
||||
### 发送single类型的消息
|
||||
```php
|
||||
$title = "乔布斯 20 年前想打造一间苹果咖啡厅,而它正是 Apple Store 的前身";
|
||||
$text = "![screenshot](@lADOpwk3K80C0M0FoA) \n".
|
||||
" #### 乔布斯 20 年前想打造的苹果咖啡厅 \n\n".
|
||||
" Apple Store 的设计正从原来满满的科技感走向生活化,而其生活化的走向其实可以追溯到 20 年前苹果一个建立咖啡馆的计划";
|
||||
|
||||
ding()->actionCard($title,$text,1)
|
||||
->single("阅读全文","https://www.dingtalk.com/")
|
||||
->send()
|
||||
```
|
||||
### 发送btns类型的消息
|
||||
|
||||
```php
|
||||
ding()->actionCard($title,$text,1)
|
||||
->addButtons("内容不错","https://www.dingtalk.com/")
|
||||
->addButtons("不感兴趣","https://www.dingtalk.com/")
|
||||
->send();
|
||||
```
|
||||
|
||||
## 发送Feed类型的消息
|
||||
|
||||
```php
|
||||
$messageUrl = "https://mp.weixin.qq.com/s?__biz=MzA4NjMwMTA2Ng==&mid=2650316842&idx=1&sn=60da3ea2b29f1dcc43a7c8e4a7c97a16&scene=2&srcid=09189AnRJEdIiWVaKltFzNTw&from=timeline&isappinstalled=0&key=&ascene=2&uin=&devicetype=android-23&version=26031933&nettype=WIFI";
|
||||
$picUrl = "https://www.dingtalk.com";
|
||||
ding()->feed()
|
||||
->addLinks('时代的火车向前开',$messageUrl,$picUrl)
|
||||
->addLinks('时代的火车向前开2',$messageUrl,$picUrl)
|
||||
->send();
|
||||
```
|
||||
## 多机器人消息发送
|
||||
|
||||
### 发送纯文字消息
|
||||
```php
|
||||
ding('我就是我, xxx 是不一样的烟火','other')
|
||||
```
|
||||
or
|
||||
```php
|
||||
ding()->with('other')->text('我就是我, xxx 是不一样的烟火');
|
||||
```
|
||||
|
||||
### 通过其他机器人发送其他类型消息
|
||||
```php
|
||||
ding()->with('other')->markdown($title,$markdown);
|
||||
|
||||
ding()->with('other')
|
||||
->feed()
|
||||
->addLinks('时代的火车向前开',$messageUrl,$picUrl)
|
||||
->addLinks('时代的火车向前开2',$messageUrl,$picUrl)
|
||||
->send();
|
||||
```
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
{
|
||||
"name": "ykxiao/dm-ding-notice",
|
||||
"description": "a dingtalk robot message handle for send message",
|
||||
"keywords": ["laravel", "ding talk", "ding notice"],
|
||||
"require": {
|
||||
"php": ">=7.0",
|
||||
"guzzlehttp/guzzle": "^6.2|^7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^5.7",
|
||||
"mockery/mockery": "^1.2"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"DingNotice\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/helpers.php"
|
||||
]
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"DingNotice\\Tests\\": "tests"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"DingNotice\\DingNoticeServiceProvider"
|
||||
]
|
||||
}
|
||||
},
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "ykxiao",
|
||||
"email": "yk_9001@gmail.com"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
|
||||
// 默认发送的机器人
|
||||
|
||||
'default' => [
|
||||
// 是否要开启机器人,关闭则不再发送消息
|
||||
'enabled' => env('DING_ENABLED',true),
|
||||
// 机器人的access_token
|
||||
'token' => env('DING_TOKEN',''),
|
||||
// 钉钉请求的超时时间
|
||||
'timeout' => env('DING_TIME_OUT',2.0),
|
||||
// 是否开启ss认证
|
||||
'ssl_verify' => env('DING_SSL_VERIFY',true),
|
||||
// 开启安全配置
|
||||
'secret' => env('DING_SECRET',true),
|
||||
],
|
||||
|
||||
'other' => [
|
||||
'enabled' => env('OTHER_DING_ENABLED',true),
|
||||
|
||||
'token' => env('OTHER_DING_TOKEN',''),
|
||||
|
||||
'timeout' => env('OTHER_DING_TIME_OUT',2.0),
|
||||
|
||||
'ssl_verify' => env('DING_SSL_VERIFY',true),
|
||||
|
||||
'secret' => env('DING_SECRET',true),
|
||||
]
|
||||
];
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit backupGlobals="false"
|
||||
backupStaticAttributes="false"
|
||||
bootstrap="./vendor/autoload.php"
|
||||
colors="true"
|
||||
convertErrorsToExceptions="true"
|
||||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
processIsolation="false"
|
||||
stopOnFailure="false">
|
||||
<testsuites>
|
||||
<testsuite name="Unit">
|
||||
<directory>./tests/Unit</directory>
|
||||
</testsuite>
|
||||
<testsuite name="Feature">
|
||||
<directory>./tests/Feature</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<filter>
|
||||
<whitelist processUncoveredFilesFromWhitelist="true">
|
||||
<directory suffix=".php">./src</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</phpunit>
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace DingNotice;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class DingNoticeServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Bootstrap services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
$this->publishes([
|
||||
__DIR__ . '/../config/ding.php' => base_path('config/ding.php'),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->registerLaravelBindings();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Register Laravel bindings.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerLaravelBindings()
|
||||
{
|
||||
$this->app->singleton(DingTalk::class, function ($app) {
|
||||
return new DingTalk($app['config']['ding']);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
<?php
|
||||
|
||||
namespace DingNotice;
|
||||
|
||||
class DingTalk
|
||||
{
|
||||
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
protected $config;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $robot = 'default';
|
||||
/**
|
||||
* @var DingTalkService
|
||||
*/
|
||||
protected $dingTalkService;
|
||||
|
||||
protected $client;
|
||||
|
||||
/**
|
||||
* DingTalk constructor.
|
||||
* @param $config
|
||||
* @param SendClient $client
|
||||
*/
|
||||
public function __construct($config,$client = null)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->client = $client;
|
||||
$this->with();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $robot
|
||||
* @return $this
|
||||
*/
|
||||
public function with($robot = 'default'){
|
||||
$this->robot = $robot;
|
||||
$this->dingTalkService = new DingTalkService($this->config[$robot],$this->client);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @return mixed
|
||||
*/
|
||||
public function text($content = ''){
|
||||
return $this->dingTalkService
|
||||
->setTextMessage($content)
|
||||
->send();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $title
|
||||
* @param $text
|
||||
* @return mixed
|
||||
*/
|
||||
public function action($title, $text){
|
||||
return $this->dingTalkService
|
||||
->setActionCardMessage($title,$text);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $mobiles
|
||||
* @param bool $atAll
|
||||
* @return $this
|
||||
*/
|
||||
public function at($mobiles = [], $atAll = false){
|
||||
$this->dingTalkService
|
||||
->setAt($mobiles,$atAll);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $title
|
||||
* @param $text
|
||||
* @param $url
|
||||
* @param string $picUrl
|
||||
* @return mixed
|
||||
*/
|
||||
public function link($title, $text, $url, $picUrl = ''){
|
||||
return $this->dingTalkService
|
||||
->setLinkMessage($title,$text,$url,$picUrl)
|
||||
->send();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $title
|
||||
* @param $markdown
|
||||
* @return mixed
|
||||
*/
|
||||
public function markdown($title, $markdown){
|
||||
return $this->dingTalkService
|
||||
->setMarkdownMessage($title,$markdown)
|
||||
->send();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $title
|
||||
* @param $markdown
|
||||
* @param int $hideAvatar
|
||||
* @param int $btnOrientation
|
||||
* @return mixed
|
||||
*/
|
||||
public function actionCard($title, $markdown, $hideAvatar = 0, $btnOrientation = 0){
|
||||
return $this->dingTalkService
|
||||
->setActionCardMessage($title,$markdown,$hideAvatar,$btnOrientation);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function feed(){
|
||||
return $this->dingTalkService
|
||||
->setFeedCardMessage();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,168 @@
|
|||
<?php
|
||||
|
||||
namespace DingNotice;
|
||||
|
||||
use DingNotice\Messages\ActionCard;
|
||||
use DingNotice\Messages\FeedCard;
|
||||
use DingNotice\Messages\Link;
|
||||
use DingNotice\Messages\Markdown;
|
||||
use DingNotice\Messages\Message;
|
||||
use DingNotice\Messages\Text;
|
||||
use GuzzleHttp\Client;
|
||||
|
||||
class DingTalkService
|
||||
{
|
||||
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* @var Message
|
||||
*/
|
||||
protected $message;
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $mobiles = [];
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $atAll = false;
|
||||
|
||||
/**
|
||||
* @var SendClient
|
||||
*/
|
||||
protected $client;
|
||||
|
||||
/**
|
||||
* DingTalkService constructor.
|
||||
* @param $config
|
||||
* @param null $client
|
||||
*/
|
||||
public function __construct($config, SendClient $client = null)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->setTextMessage('null');
|
||||
|
||||
if ($client != null) {
|
||||
$this->client = $client;
|
||||
return;
|
||||
}
|
||||
$this->client = $this->createClient($config);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Message $message
|
||||
*/
|
||||
public function setMessage($message)
|
||||
{
|
||||
$this->message = $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getMessage()
|
||||
{
|
||||
return $this->message->getMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $mobiles
|
||||
* @param bool $atAll
|
||||
*/
|
||||
public function setAt($mobiles = [], $atAll = false)
|
||||
{
|
||||
$this->mobiles = $mobiles;
|
||||
$this->atAll = $atAll;
|
||||
if ($this->message) {
|
||||
$this->message->sendAt($mobiles, $atAll);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* create a guzzle client
|
||||
* @return HttpClient
|
||||
* @author wangju 2019-05-17 20:25
|
||||
*/
|
||||
protected function createClient($config)
|
||||
{
|
||||
$client = new HttpClient($config);
|
||||
return $client;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $content
|
||||
* @return $this
|
||||
*/
|
||||
public function setTextMessage($content)
|
||||
{
|
||||
$this->message = new Text($content);
|
||||
$this->message->sendAt($this->mobiles, $this->atAll);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $title
|
||||
* @param $text
|
||||
* @param $messageUrl
|
||||
* @param string $picUrl
|
||||
* @return $this
|
||||
*/
|
||||
public function setLinkMessage($title, $text, $messageUrl, $picUrl = '')
|
||||
{
|
||||
$this->message = new Link($title, $text, $messageUrl, $picUrl);
|
||||
$this->message->sendAt($this->mobiles, $this->atAll);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $title
|
||||
* @param $text
|
||||
* @return $this
|
||||
*/
|
||||
public function setMarkdownMessage($title, $markdown)
|
||||
{
|
||||
$this->message = new Markdown($title, $markdown);
|
||||
$this->message->sendAt($this->mobiles, $this->atAll);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $title
|
||||
* @param $text
|
||||
* @param int $hideAvatar
|
||||
* @param int $btnOrientation
|
||||
* @return ActionCard|Message
|
||||
*/
|
||||
public function setActionCardMessage($title, $markdown, $hideAvatar = 0, $btnOrientation = 0)
|
||||
{
|
||||
$this->message = new ActionCard($this, $title, $markdown, $hideAvatar, $btnOrientation);
|
||||
$this->message->sendAt($this->mobiles, $this->atAll);
|
||||
return $this->message;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return FeedCard|Message
|
||||
*/
|
||||
public function setFeedCardMessage()
|
||||
{
|
||||
$this->message = new FeedCard($this);
|
||||
$this->message->sendAt($this->mobiles, $this->atAll);
|
||||
return $this->message;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|array
|
||||
*/
|
||||
public function send()
|
||||
{
|
||||
if (!$this->config['enabled']) {
|
||||
return false;
|
||||
}
|
||||
return $this->client->send($this->message->getBody());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: wangju
|
||||
* Date: 2019-05-17
|
||||
* Time: 20:38
|
||||
*/
|
||||
|
||||
namespace DingNotice;
|
||||
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
|
||||
class HttpClient implements SendClient
|
||||
{
|
||||
protected $client;
|
||||
protected $config;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $hookUrl = "https://oapi.dingtalk.com/robot/send";
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $accessToken = "";
|
||||
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->setAccessToken();
|
||||
$this->client = $this->createClient();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function setAccessToken(){
|
||||
$this->accessToken = $this->config['token'];
|
||||
}
|
||||
|
||||
/**
|
||||
* create a guzzle client
|
||||
* @return Client
|
||||
* @author wangju 2019-05-17 20:25
|
||||
*/
|
||||
protected function createClient()
|
||||
{
|
||||
$client = new Client([
|
||||
'timeout' => $this->config['timeout'] ?? 2.0,
|
||||
]);
|
||||
return $client;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getRobotUrl()
|
||||
{
|
||||
$query['access_token'] = $this->accessToken;
|
||||
if (isset($this->config['secret']) && $secret = $this->config['secret']) {
|
||||
$timestamp = time() . sprintf('%03d', rand(1, 999));
|
||||
$sign = hash_hmac('sha256', $timestamp . "\n" . $secret, $secret, true);
|
||||
$query['timestamp'] = $timestamp;
|
||||
$query['sign'] = base64_encode($sign);
|
||||
}
|
||||
return $this->hookUrl . "?" . http_build_query($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* send message
|
||||
* @param $url
|
||||
* @param $params
|
||||
* @return array
|
||||
* @author wangju 2019-05-17 20:48
|
||||
*/
|
||||
public function send($params): array
|
||||
{
|
||||
$request = $this->client->post($this->getRobotUrl(), [
|
||||
'body' => json_encode($params),
|
||||
'headers' => [
|
||||
'Content-Type' => 'application/json',
|
||||
],
|
||||
'verify' => $this->config['ssl_verify'] ?? true,
|
||||
]);
|
||||
|
||||
$result = $request->getBody()->getContents();
|
||||
return json_decode($result, true) ?? [];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
namespace DingNotice\Messages;
|
||||
|
||||
use DingNotice\DingTalkService;
|
||||
|
||||
class ActionCard extends Message
|
||||
{
|
||||
|
||||
protected $service;
|
||||
|
||||
public function __construct(DingTalkService $service,$title, $markdown, $hideAvatar = 0, $btnOrientation = 0)
|
||||
{
|
||||
$this->service = $service;
|
||||
$this->setMessage($title,$markdown,$hideAvatar,$btnOrientation);
|
||||
}
|
||||
|
||||
public function setMessage($title, $markdown, $hideAvatar = 0, $btnOrientation = 0){
|
||||
$this->message = [
|
||||
'msgtype' => 'actionCard',
|
||||
'actionCard' => [
|
||||
'title' => $title,
|
||||
'text' => $markdown,
|
||||
'hideAvatar' => $hideAvatar,
|
||||
'btnOrientation' => $btnOrientation
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public function single($title,$url){
|
||||
$this->message['actionCard']['singleTitle'] = $title;
|
||||
$this->message['actionCard']['singleURL'] = $url;
|
||||
$this->service->setMessage($this);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addButtons($title,$url){
|
||||
$this->message['actionCard']['btns'][] = [
|
||||
'title' => $title,
|
||||
'actionURL' => $url
|
||||
];
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function send(){
|
||||
$this->service->setMessage($this);
|
||||
return $this->service->send();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
namespace DingNotice\Messages;
|
||||
|
||||
use DingNotice\DingTalkService;
|
||||
|
||||
class FeedCard extends Message
|
||||
{
|
||||
protected $service;
|
||||
|
||||
public function __construct(DingTalkService $service)
|
||||
{
|
||||
$this->service = $service;
|
||||
$this->setMessage();
|
||||
|
||||
}
|
||||
|
||||
public function setMessage(){
|
||||
$this->message = [
|
||||
'feedCard' => [
|
||||
'links' => []
|
||||
],
|
||||
'msgtype' => 'feedCard'
|
||||
];
|
||||
}
|
||||
|
||||
public function addLinks($title,$messageUrl,$picUrl){
|
||||
$this->message['feedCard']['links'][] = [
|
||||
'title' => $title,
|
||||
'messageURL' => $messageUrl,
|
||||
'picURL' => $picUrl
|
||||
];
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function send(){
|
||||
$this->service->setMessage($this);
|
||||
return $this->service->send();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace DingNotice\Messages;
|
||||
|
||||
class Link extends Message
|
||||
{
|
||||
|
||||
public function __construct($title,$text,$messageUrl,$picUrl = '')
|
||||
{
|
||||
$this->setMessage($title,$text,$messageUrl,$picUrl);
|
||||
}
|
||||
|
||||
public function setMessage($title,$text,$messageUrl,$picUrl = ''){
|
||||
$this->message = [
|
||||
'msgtype' => 'link',
|
||||
'link' => [
|
||||
'text' => $text,
|
||||
'title' => $title,
|
||||
'picUrl' => $picUrl,
|
||||
'messageUrl' => $messageUrl
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
namespace DingNotice\Messages;
|
||||
|
||||
class Markdown extends Message
|
||||
{
|
||||
public function __construct($title,$markdown)
|
||||
{
|
||||
$this->setMessage($title,$markdown);
|
||||
}
|
||||
|
||||
public function setMessage($title,$markdown){
|
||||
$this->message = [
|
||||
'msgtype' => 'markdown',
|
||||
'markdown' => [
|
||||
'title' => $title,
|
||||
'text' => $markdown
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
namespace DingNotice\Messages;
|
||||
|
||||
abstract class Message
|
||||
{
|
||||
protected $message = [];
|
||||
protected $at;
|
||||
|
||||
|
||||
public function getMessage(){
|
||||
return $this->message;
|
||||
}
|
||||
|
||||
protected function makeAt($mobiles = [],$atAll = false){
|
||||
return [
|
||||
'at' => [
|
||||
'atMobiles' => $mobiles,
|
||||
'isAtAll' => $atAll
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public function sendAt($mobiles = [],$atAll = false){
|
||||
$this->at = $this->makeAt($mobiles,$atAll);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getBody(){
|
||||
|
||||
if (empty($this->at)){
|
||||
$this->sendAt();
|
||||
}
|
||||
return $this->message + $this->at;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
namespace DingNotice\Messages;
|
||||
|
||||
class Text extends Message
|
||||
{
|
||||
public function __construct($content)
|
||||
{
|
||||
$this->message = [
|
||||
'msgtype' => 'text',
|
||||
'text' => [
|
||||
'content' => $content
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: wangju
|
||||
* Date: 2019-05-17
|
||||
* Time: 20:37
|
||||
*/
|
||||
|
||||
namespace DingNotice;
|
||||
|
||||
|
||||
interface SendClient
|
||||
{
|
||||
public function send($params): array;
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
use DingNotice\DingTalk;
|
||||
|
||||
if (!function_exists('ding')){
|
||||
|
||||
/**
|
||||
* @return bool|DingTalk
|
||||
*/
|
||||
function ding(){
|
||||
|
||||
$arguments = func_get_args();
|
||||
|
||||
$dingTalk = app(DingTalk::class);
|
||||
|
||||
if (empty($arguments)) {
|
||||
return $dingTalk;
|
||||
}
|
||||
|
||||
if (is_string($arguments[0])) {
|
||||
$robot = $arguments[1] ?? 'default';
|
||||
return $dingTalk->with($robot)->text($arguments[0]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
namespace DingNotice\Tests\Feature;
|
||||
|
||||
use DingNotice\Tests\TestCase;
|
||||
|
||||
|
||||
class ActionTest extends TestCase
|
||||
{
|
||||
protected $title = "乔布斯 20 年前想打造一间苹果咖啡厅,而它正是 Apple Store 的前身";
|
||||
protected $text = "![screenshot](@lADOpwk3K80C0M0FoA) \n".
|
||||
" #### 乔布斯 20 年前想打造的苹果咖啡厅 \n\n".
|
||||
" Apple Store 的设计正从原来满满的科技感走向生活化,而其生活化的走向其实可以追溯到 20 年前苹果一个建立咖啡馆的计划";
|
||||
|
||||
|
||||
public function __construct($name = null, array $data = [], $dataName = '')
|
||||
{
|
||||
parent::__construct($name, $data, $dataName);
|
||||
$this->setUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* available content to set
|
||||
* @param $content
|
||||
* @return bool
|
||||
* @author wangju 2019-05-17 21:50
|
||||
*/
|
||||
protected function matchContent($content)
|
||||
{
|
||||
return $content['title'] && $content['text'];
|
||||
}
|
||||
|
||||
/**
|
||||
* A basic test example.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testPushActionSingleMessage()
|
||||
{
|
||||
|
||||
$result = $this->ding
|
||||
->actionCard($this->title,$this->text,1)
|
||||
->single("阅读全文","https://www.dingtalk.com/")
|
||||
->send();
|
||||
$this->assertSame([
|
||||
'errmsg' => 'ok',
|
||||
'errcode' => 0
|
||||
],$result);
|
||||
}
|
||||
|
||||
public function testPushActionBtnsMessageAtAllUser(){
|
||||
$result = $result = $this->ding
|
||||
->actionCard($this->title,$this->text,1)
|
||||
->addButtons("内容不错","https://www.dingtalk.com/")
|
||||
->addButtons("不感兴趣","https://www.dingtalk.com/")
|
||||
->send();
|
||||
$this->assertSame([
|
||||
'errmsg' => 'ok',
|
||||
'errcode' => 0
|
||||
],$result);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
namespace DingNotice\Tests\Feature;
|
||||
|
||||
use DingNotice\Tests\TestCase;
|
||||
|
||||
|
||||
class FeedTest extends TestCase
|
||||
{
|
||||
protected $messageUrl = "https://mp.weixin.qq.com/s?__biz=MzA4NjMwMTA2Ng==&mid=2650316842&idx=1&sn=60da3ea2b29f1dcc43a7c8e4a7c97a16&scene=2&srcid=09189AnRJEdIiWVaKltFzNTw&from=timeline&isappinstalled=0&key=&ascene=2&uin=&devicetype=android-23&version=26031933&nettype=WIFI";
|
||||
protected $picUrl = "https://www.dingtalk.com";
|
||||
|
||||
public function __construct($name = null, array $data = [], $dataName = '')
|
||||
{
|
||||
parent::__construct($name, $data, $dataName);
|
||||
$this->setUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* available content to set
|
||||
* @param $content
|
||||
* @return bool
|
||||
* @author wangju 2019-05-17 21:50
|
||||
*/
|
||||
protected function matchContent($content)
|
||||
{
|
||||
if (empty($content)){
|
||||
return false;
|
||||
}
|
||||
return array_reduce($content,function ($carry,$item){
|
||||
if ($carry === null) return true;
|
||||
return $carry && $item['title'] && $item['messageURL'] && $item['picURL'];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* A basic test example.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testPushTextMessage()
|
||||
{
|
||||
$result =$this->ding->text("我就是我,@{$this->testUser} 是不一样的烟火");
|
||||
$this->assertSame([
|
||||
'errmsg' => 'ok',
|
||||
'errcode' => 0
|
||||
],$result);
|
||||
}
|
||||
|
||||
public function testPushTextMessageAtAllUser(){
|
||||
$result =$this->ding
|
||||
->feed()
|
||||
->addLinks('时代的火车向前开',$this->messageUrl,$this->picUrl)
|
||||
->addLinks('时代的火车向前开2',$this->messageUrl,$this->picUrl)
|
||||
->send();
|
||||
|
||||
$this->assertSame([
|
||||
'errmsg' => 'ok',
|
||||
'errcode' => 0
|
||||
],$result);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
namespace DingNotice\Tests\Feature;
|
||||
|
||||
use DingNotice\Tests\TestCase;
|
||||
|
||||
|
||||
class LinkTest extends TestCase
|
||||
{
|
||||
|
||||
protected $title = "自定义机器人协议";
|
||||
protected $text = "群机器人是钉钉群的高级扩展功能。群机器人可以将第三方服务的信息聚合到群聊中,实现自动化的信息同步。例如:通过聚合GitHub,GitLab等源码管理服务,实现源码更新同步;通过聚合Trello,JIRA等项目协调服务,实现项目信息同步。不仅如此,群机器人支持Webhook协议的自定义接入,支持更多可能性,例如:你可将运维报警提醒通过自定义机器人聚合到钉钉群。";
|
||||
protected $picUrl = "";
|
||||
protected $messageUrl = "https://open-doc.dingtalk.com/docs/doc.htm?spm=a219a.7629140.0.0.Rqyvqo&treeId=257&articleId=105735&docType=1";
|
||||
|
||||
public function __construct($name = null, array $data = [], $dataName = '')
|
||||
{
|
||||
parent::__construct($name, $data, $dataName);
|
||||
$this->setUp();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* available content to set
|
||||
* @param $content
|
||||
* @return bool
|
||||
* @author wangju 2019-05-17 21:50
|
||||
*/
|
||||
protected function matchContent($content)
|
||||
{
|
||||
return $content['text'] && $content['title'] && $content['messageUrl'];
|
||||
}
|
||||
|
||||
/**
|
||||
* A basic test example.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testPushLinkMessage()
|
||||
{
|
||||
$result = $this->ding->link($this->title,$this->text,$this->messageUrl,$this->picUrl);
|
||||
$this->assertSame([
|
||||
'errmsg' => 'ok',
|
||||
'errcode' => 0
|
||||
],$result);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
namespace DingNotice\Tests\Feature;
|
||||
|
||||
use DingNotice\Tests\TestCase;
|
||||
|
||||
|
||||
class MarkDownTest extends TestCase
|
||||
{
|
||||
protected $title = "杭州天气";
|
||||
protected $markdown = "#### 杭州天气 \n ".
|
||||
"> 9度,@1825718XXXX 西北风1级,空气良89,相对温度73%\n\n ".
|
||||
"> ![screenshot](http://i01.lw.aliimg.com/media/lALPBbCc1ZhJGIvNAkzNBLA_1200_588.png)\n".
|
||||
"> ###### 10点20分发布 [天气](http://www.thinkpage.cn/) ";
|
||||
|
||||
public function __construct($name = null, array $data = [], $dataName = '')
|
||||
{
|
||||
parent::__construct($name, $data, $dataName);
|
||||
$this->setUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* available content to set
|
||||
* @param $content
|
||||
* @return bool
|
||||
* @author wangju 2019-05-17 21:50
|
||||
*/
|
||||
protected function matchContent($content)
|
||||
{
|
||||
return $content['title'] && $content['text'];
|
||||
}
|
||||
|
||||
/**
|
||||
* A basic test example.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testPushMarkdownMessage()
|
||||
{
|
||||
$result =$this->ding->markdown($this->title,$this->markdown);
|
||||
$this->assertSame([
|
||||
'errmsg' => 'ok',
|
||||
'errcode' => 0
|
||||
],$result);
|
||||
}
|
||||
|
||||
public function testPushMarkdownMessageAtAllUser(){
|
||||
$result =$this->ding
|
||||
->at([],true)
|
||||
->markdown($this->title,$this->markdown);
|
||||
$this->assertSame([
|
||||
'errmsg' => 'ok',
|
||||
'errcode' => 0
|
||||
],$result);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
|
||||
namespace DingNotice\Tests\Feature;
|
||||
|
||||
use DingNotice\SendClient;
|
||||
use DingNotice\Tests\TestCase;
|
||||
|
||||
|
||||
class TextTest extends TestCase
|
||||
{
|
||||
public function __construct($name = null, array $data = [], $dataName = '')
|
||||
{
|
||||
parent::__construct($name, $data, $dataName);
|
||||
$this->setUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* available content to set
|
||||
* @param $content
|
||||
* @return bool
|
||||
* @author wangju 2019-05-17 21:50
|
||||
*/
|
||||
protected function matchContent($content)
|
||||
{
|
||||
$text = $content['content'];
|
||||
return !empty($text);
|
||||
}
|
||||
|
||||
/**
|
||||
* A basic test example.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testPushTextMessage()
|
||||
{
|
||||
$result =$this->ding->text("我就是我,@{$this->testUser} 是不一样的烟火");
|
||||
$this->assertSame([
|
||||
'errmsg' => 'ok',
|
||||
'errcode' => 0
|
||||
],$result);
|
||||
}
|
||||
|
||||
public function testPushTextMessageAtAllUser(){
|
||||
$result =$this->ding
|
||||
->at([],true)
|
||||
->text("我就是我,@{$this->testUser} 是不一样的烟火");
|
||||
$this->assertSame([
|
||||
'errmsg' => 'ok',
|
||||
'errcode' => 0
|
||||
],$result);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
|
||||
namespace DingNotice\Tests;
|
||||
|
||||
use DingNotice\DingTalk;
|
||||
use DingNotice\SendClient;
|
||||
use PHPUnit\Framework\TestCase as BaseTestCase;
|
||||
|
||||
abstract class TestCase extends BaseTestCase
|
||||
{
|
||||
/**
|
||||
* @var DingTalk
|
||||
*/
|
||||
protected $ding;
|
||||
protected $testUser;
|
||||
protected $config;
|
||||
|
||||
public function setUp(){
|
||||
|
||||
$token = 'f80be582aafed07cfced271c333c7ba7f46b873ebf7168e570919296b8062bad';
|
||||
$this->testUser = '18888888888';
|
||||
|
||||
$robot1['timeout'] = 30.0;
|
||||
$robot1['enabled'] = true;
|
||||
$robot1['token'] = $token;
|
||||
$robot1['secret'] = 'SECcfc6343d91e588d1f83dcf6d725a0208f79607726560ca2be135b437c62523b5';
|
||||
$config['default'] = $robot1;
|
||||
|
||||
$this->config = $config;
|
||||
$this->ding = $this->mockDingClient();
|
||||
}
|
||||
|
||||
/**
|
||||
* mock ding client
|
||||
* @param null $client
|
||||
* @return DingTalk
|
||||
* @author wangju 2019-05-17 20:53
|
||||
*/
|
||||
protected function mockDingClient($client = null)
|
||||
{
|
||||
$client = \Mockery::mock(SendClient::class);
|
||||
$client->shouldReceive('send')->withArgs(function ($arg) {
|
||||
$messageType = $arg['msgtype'];
|
||||
|
||||
if (!in_array($messageType, ['text', 'actionCard', 'feedCard', 'link', 'markdown'])) {
|
||||
return false;
|
||||
}
|
||||
if (!array_key_exists($messageType, $arg)) {
|
||||
return false;
|
||||
}
|
||||
return $this->matchContent($arg[$messageType]);
|
||||
})->andReturn([
|
||||
'errmsg' => 'ok',
|
||||
'errcode' => 0
|
||||
]);
|
||||
$ding = new DingTalk($this->config, $client);
|
||||
return $ding;
|
||||
}
|
||||
|
||||
protected function matchContent($content)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue