songxingwei 2 years ago
parent
commit
1dbcc0dd7e
54 changed files with 3515 additions and 6 deletions
  1. 1 1
      composer.json
  2. 11 2
      vendor/composer/InstalledVersions.php
  3. 1 0
      vendor/composer/autoload_psr4.php
  4. 5 0
      vendor/composer/autoload_static.php
  5. 50 0
      vendor/composer/installed.json
  6. 11 2
      vendor/composer/installed.php
  7. 18 0
      vendor/jpush/jpush/.gitignore
  8. 13 0
      vendor/jpush/jpush/.travis.yml
  9. 21 0
      vendor/jpush/jpush/LICENSE
  10. 121 0
      vendor/jpush/jpush/README.md
  11. 10 0
      vendor/jpush/jpush/autoload.php
  12. 31 0
      vendor/jpush/jpush/composer.json
  13. 494 0
      vendor/jpush/jpush/doc/api.md
  14. 28 0
      vendor/jpush/jpush/doc/grouppush.md
  15. 56 0
      vendor/jpush/jpush/doc/http2.md
  16. 14 0
      vendor/jpush/jpush/examples/admin_example.php
  17. 35 0
      vendor/jpush/jpush/examples/batch_push_example.php
  18. 7 0
      vendor/jpush/jpush/examples/cid_example.php
  19. 10 0
      vendor/jpush/jpush/examples/config.php.example
  20. 5 0
      vendor/jpush/jpush/examples/devices/delete_alias_example.php
  21. 5 0
      vendor/jpush/jpush/examples/devices/delete_tag_example.php
  22. 6 0
      vendor/jpush/jpush/examples/devices/get_alias_devices_example.php
  23. 6 0
      vendor/jpush/jpush/examples/devices/get_devices_example.php
  24. 13 0
      vendor/jpush/jpush/examples/devices/get_devices_status_example.php
  25. 6 0
      vendor/jpush/jpush/examples/devices/get_tags_example.php
  26. 56 0
      vendor/jpush/jpush/examples/devices/update_device_example.php
  27. 29 0
      vendor/jpush/jpush/examples/devices/update_tag_example.php
  28. 24 0
      vendor/jpush/jpush/examples/grouppush_example.php
  29. 36 0
      vendor/jpush/jpush/examples/huawei_push_example.php
  30. 140 0
      vendor/jpush/jpush/examples/push_example.php
  31. 5 0
      vendor/jpush/jpush/examples/reports/messages_detail_example.php
  32. 5 0
      vendor/jpush/jpush/examples/reports/received_detail_example.php
  33. 26 0
      vendor/jpush/jpush/examples/schedule_example.php
  34. 24 0
      vendor/jpush/jpush/examples/zone_examples.php
  35. 15 0
      vendor/jpush/jpush/phpunit.xml.dist
  36. 42 0
      vendor/jpush/jpush/src/JPush/AdminClient.php
  37. 71 0
      vendor/jpush/jpush/src/JPush/Client.php
  38. 16 0
      vendor/jpush/jpush/src/JPush/Config.php
  39. 224 0
      vendor/jpush/jpush/src/JPush/DevicePayload.php
  40. 9 0
      vendor/jpush/jpush/src/JPush/Exceptions/APIConnectionException.php
  41. 36 0
      vendor/jpush/jpush/src/JPush/Exceptions/APIRequestException.php
  42. 9 0
      vendor/jpush/jpush/src/JPush/Exceptions/JPushException.php
  43. 25 0
      vendor/jpush/jpush/src/JPush/Exceptions/ServiceNotAvaliable.php
  44. 139 0
      vendor/jpush/jpush/src/JPush/Http.php
  45. 761 0
      vendor/jpush/jpush/src/JPush/PushPayload.php
  46. 109 0
      vendor/jpush/jpush/src/JPush/ReportPayload.php
  47. 182 0
      vendor/jpush/jpush/src/JPush/SchedulePayload.php
  48. 4 0
      vendor/jpush/jpush/src/JPush/version.php
  49. 131 0
      vendor/jpush/jpush/tests/JPush/DevicePayloadTest.php
  50. 315 0
      vendor/jpush/jpush/tests/JPush/PushPayloadTest.php
  51. 77 0
      vendor/jpush/jpush/tests/JPush/ReportPayloadTest.php
  52. 18 0
      vendor/jpush/jpush/tests/JPush/SchedulePayloadTest.php
  53. 8 0
      vendor/jpush/jpush/tests/bootstrap.php
  54. 1 1
      vendor/services.php

+ 1 - 1
composer.json

@@ -41,7 +41,7 @@
     "alibabacloud/cloudauth-20190307": "^2.0",
     "yansongda/pay": "^2.10",
     "phpoffice/phpword": "^1.0",
-    "jpush/jpush": "^3.5"
+    "jpush/jpush": "^3.6"
   },
   "autoload": {
     "psr-0": {

+ 11 - 2
vendor/composer/InstalledVersions.php

@@ -32,7 +32,7 @@ private static $installed = array (
     'aliases' => 
     array (
     ),
-    'reference' => 'd4e10a9d535cd232adf094dc4567b7e0f282dee1',
+    'reference' => 'c80e03bd378ffbedb65ab5e8b2a6602ecbf0d367',
     'name' => 'zoujingli/thinkadmin',
   ),
   'versions' => 
@@ -298,6 +298,15 @@ private static $installed = array (
       ),
       'reference' => '877ff07f80d75444b20f0f252e0e5f67e82f6eb1',
     ),
+    'jpush/jpush' => 
+    array (
+      'pretty_version' => 'v3.6.8',
+      'version' => '3.6.8.0',
+      'aliases' => 
+      array (
+      ),
+      'reference' => 'ebb191e8854a35c3fb7a6626028b3a23132cbe2c',
+    ),
     'laminas/laminas-escaper' => 
     array (
       'pretty_version' => '2.12.0',
@@ -807,7 +816,7 @@ private static $installed = array (
       'aliases' => 
       array (
       ),
-      'reference' => 'd4e10a9d535cd232adf094dc4567b7e0f282dee1',
+      'reference' => 'c80e03bd378ffbedb65ab5e8b2a6602ecbf0d367',
     ),
     'zoujingli/wechat-developer' => 
     array (

+ 1 - 0
vendor/composer/autoload_psr4.php

@@ -52,6 +52,7 @@ return array(
     'Mimey\\' => array($vendorDir . '/ralouphie/mimey/src'),
     'Laminas\\Escaper\\' => array($vendorDir . '/laminas/laminas-escaper/src'),
     'JmesPath\\' => array($vendorDir . '/mtdowling/jmespath.php/src'),
+    'JPush\\' => array($vendorDir . '/jpush/jpush/src/JPush'),
     'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
     'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'),
     'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'),

+ 5 - 0
vendor/composer/autoload_static.php

@@ -109,6 +109,7 @@ class ComposerStaticInit418695b1e8bbb0edd5aafcc0b225847b
         'J' => 
         array (
             'JmesPath\\' => 9,
+            'JPush\\' => 6,
         ),
         'G' => 
         array (
@@ -343,6 +344,10 @@ class ComposerStaticInit418695b1e8bbb0edd5aafcc0b225847b
         array (
             0 => __DIR__ . '/..' . '/mtdowling/jmespath.php/src',
         ),
+        'JPush\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/jpush/jpush/src/JPush',
+        ),
         'GuzzleHttp\\Psr7\\' => 
         array (
             0 => __DIR__ . '/..' . '/guzzlehttp/psr7/src',

+ 50 - 0
vendor/composer/installed.json

@@ -1836,6 +1836,56 @@
             "install-path": "../hg/apidoc-thinkphp"
         },
         {
+            "name": "jpush/jpush",
+            "version": "v3.6.8",
+            "version_normalized": "3.6.8.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/jpush/jpush-api-php-client.git",
+                "reference": "ebb191e8854a35c3fb7a6626028b3a23132cbe2c"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/jpush/jpush-api-php-client/zipball/ebb191e8854a35c3fb7a6626028b3a23132cbe2c",
+                "reference": "ebb191e8854a35c3fb7a6626028b3a23132cbe2c",
+                "shasum": ""
+            },
+            "require": {
+                "ext-curl": "*",
+                "php": ">=5.3.3"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "*"
+            },
+            "time": "2021-08-12T07:43:39+00:00",
+            "type": "library",
+            "installation-source": "dist",
+            "autoload": {
+                "psr-4": {
+                    "JPush\\": "src/JPush/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "JPush",
+                    "email": "support@jpush.cn",
+                    "homepage": "https://www.jpush.cn/",
+                    "role": "Developer"
+                }
+            ],
+            "description": "JPush API PHP Client",
+            "homepage": "https://github.com/jpush/jpush-api-php-client",
+            "support": {
+                "issues": "https://github.com/jpush/jpush-api-php-client/issues",
+                "source": "https://github.com/jpush/jpush-api-php-client/tree/v3.6.8"
+            },
+            "install-path": "../jpush/jpush"
+        },
+        {
             "name": "laminas/laminas-escaper",
             "version": "2.12.0",
             "version_normalized": "2.12.0.0",

+ 11 - 2
vendor/composer/installed.php

@@ -6,7 +6,7 @@
     'aliases' => 
     array (
     ),
-    'reference' => 'd4e10a9d535cd232adf094dc4567b7e0f282dee1',
+    'reference' => 'c80e03bd378ffbedb65ab5e8b2a6602ecbf0d367',
     'name' => 'zoujingli/thinkadmin',
   ),
   'versions' => 
@@ -272,6 +272,15 @@
       ),
       'reference' => '877ff07f80d75444b20f0f252e0e5f67e82f6eb1',
     ),
+    'jpush/jpush' => 
+    array (
+      'pretty_version' => 'v3.6.8',
+      'version' => '3.6.8.0',
+      'aliases' => 
+      array (
+      ),
+      'reference' => 'ebb191e8854a35c3fb7a6626028b3a23132cbe2c',
+    ),
     'laminas/laminas-escaper' => 
     array (
       'pretty_version' => '2.12.0',
@@ -781,7 +790,7 @@
       'aliases' => 
       array (
       ),
-      'reference' => 'd4e10a9d535cd232adf094dc4567b7e0f282dee1',
+      'reference' => 'c80e03bd378ffbedb65ab5e8b2a6602ecbf0d367',
     ),
     'zoujingli/wechat-developer' => 
     array (

+ 18 - 0
vendor/jpush/jpush/.gitignore

@@ -0,0 +1,18 @@
+*.pyc
+log/
+build/
+bin/
+.pydevproject
+.tar
+.zip
+.buildpath
+.project
+.settings/
+.idea
+composer.lock
+vendor/
+*.log
+vendor.tar.gz
+composer.phar
+vendor.zip
+examples/config.php

+ 13 - 0
vendor/jpush/jpush/.travis.yml

@@ -0,0 +1,13 @@
+language: php
+
+php:
+  - '5.3'
+  - '5.4'
+  - '5.5'
+  - '5.6'
+  - '7.0'
+
+before_script:
+  - composer install
+script:
+  - ./vendor/bin/phpunit tests

+ 21 - 0
vendor/jpush/jpush/LICENSE

@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 极光
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 121 - 0
vendor/jpush/jpush/README.md

@@ -0,0 +1,121 @@
+# JPush API PHP Client
+
+这是 JPush REST API 的 PHP 版本封装开发包,是由极光推送官方提供的,一般支持最新的 API 功能。
+
+对应的 REST API 文档: https://docs.jiguang.cn/jpush/server/push/server_overview/
+
+> 支持的 PHP 版本: 5.3.3 ~ 5.6.x, 7.x
+
+> 若需要兼容 PHP 5.3.3 以下版本,可以使用 [v3 分支的代码](https://github.com/jpush/jpush-api-php-client/tree/v3)。
+因为运行 Composer 需要 PHP 5.3.2+ 以上版本,所以其不提供 Composer 支持,
+也可以[点击链接](https://github.com/jpush/jpush-api-php-client/releases)下载 v3.4.x 版本源码。
+
+## Installation
+
+#### 使用 Composer 安装
+
+- 执行 `$ php composer.phar install` 或 `$ composer install` 进行安装。
+
+#### 直接下载源码安装
+
+> 直接下载源代码也是一种安装 SDK 的方法,不过因为有版本更新的维护问题,所以这种安装方式**十分不推荐**,但由于种种原因导致无法使用 Composer,所以我们也提供了这种情况下的备选方案。
+
+- 下载源代码包,解压到项目中
+- 在项目中引入 autoload:
+
+```php
+require 'path_to_sdk/autoload.php';
+```
+
+## Usage
+
+- [Init API](https://github.com/jpush/jpush-api-php-client/blob/master/doc/api.md#init-api)
+- [Push API](https://github.com/jpush/jpush-api-php-client/blob/master/doc/api.md#push-api)
+- [Report API](https://github.com/jpush/jpush-api-php-client/blob/master/doc/api.md#report-api)
+- [Device API](https://github.com/jpush/jpush-api-php-client/blob/master/doc/api.md#device-api)
+- [Schedule API](https://github.com/jpush/jpush-api-php-client/blob/master/doc/api.md#schedule-api)
+- [Exception Handle](https://github.com/jpush/jpush-api-php-client/blob/master/doc/api.md#schedule-api)
+- [HTTP/2 Support](https://github.com/jpush/jpush-api-php-client/blob/master/doc/http2.md)
+- [Group Push](https://github.com/jpush/jpush-api-php-client/blob/master/doc/grouppush.md)
+
+#### 初始化
+
+```php
+use JPush\Client as JPush;
+...
+...
+
+    $client = new JPush($app_key, $master_secret);
+
+...
+```
+
+OR
+
+```php
+$client = new \JPush\Client($app_key, $master_secret);
+```
+
+#### 简单推送
+
+```php
+$client->push()
+    ->setPlatform('all')
+    ->addAllAudience()
+    ->setNotificationAlert('Hello, JPush')
+    ->send();
+```
+
+#### 异常处理
+
+```php
+$pusher = $client->push();
+$pusher->setPlatform('all');
+$pusher->addAllAudience();
+$pusher->setNotificationAlert('Hello, JPush');
+try {
+    $pusher->send();
+} catch (\JPush\Exceptions\JPushException $e) {
+    // try something else here
+    print $e;
+}
+```
+
+## Examples
+
+**注意: 这只是使用样例, 不应该直接用于实际环境中!!**
+
+在下载的中的 [examples](https://github.com/jpush/jpush-api-php-client/tree/master/examples) 文件夹有简单示例代码, 开发者可以参考其中的样例快速了解该库的使用方法。
+
+**简单使用方法**
+
+先填写对应的appKey和masterSecret,可以额外设定Registration_id。
+
+若要运行 push_example.php 中的示例代码:
+
+``` bash
+# 假定当前目录为 JPush 源码所在的根目录
+$ php examples/push_example.php
+```
+> 同时也可编辑相关的示例文件,更改参数查看执行效果
+
+## Testing
+
+```bash
+# 编辑 tests/bootstrap.php 文件,填入必须的变量值
+# OR 设置相应的环境变量
+
+# 运行全部测试用例
+$ composer tests
+
+# 运行某一具体测试用例
+$ composer tests/JPush/xxTest.php
+```
+
+## Contributing
+
+Bug reports and pull requests are welcome on GitHub at https://github.com/jpush/jpush-api-php-client.
+
+## License
+
+The library is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).

+ 10 - 0
vendor/jpush/jpush/autoload.php

@@ -0,0 +1,10 @@
+<?php
+function classLoader($class)
+{
+    $path = str_replace('\\', DIRECTORY_SEPARATOR, $class);
+    $file = __DIR__ . '/src/' . $path . '.php';
+    if (file_exists($file)) {
+        require_once $file;
+    }
+}
+spl_autoload_register('classLoader');

+ 31 - 0
vendor/jpush/jpush/composer.json

@@ -0,0 +1,31 @@
+{
+    "name": "jpush/jpush",
+    "type": "library",
+    "description": "JPush API PHP Client",
+    "homepage": "https://github.com/jpush/jpush-api-php-client",
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "JPush",
+            "email": "support@jpush.cn",
+            "homepage": "https://www.jpush.cn/",
+            "role": "Developer"
+        }
+    ],
+    "require": {
+        "php": ">=5.3.3",
+        "ext-curl": "*"
+    },
+    "require-dev": {
+        "phpunit/phpunit": "*"
+    },
+    "autoload" : {
+        "psr-4": {"JPush\\": "src/JPush/"}
+    },
+    "autoload-dev": {
+        "psr-4": { "JPush\\Tests\\": "tests/" }
+    },
+    "scripts": {
+        "test": "vendor/bin/phpunit"
+    }
+}

+ 494 - 0
vendor/jpush/jpush/doc/api.md

@@ -0,0 +1,494 @@
+# 目录
+
+- [Init API](#init-api)
+- [Push API](#push-api)
+- [Report API](#report-api)
+- [Device API](#device-api)
+- [Schedule API](#schedule-api)
+- [Exception Handle](#schedule-api)
+
+> **注:PHP SDK 全面支持 namespaces 但为方便表达,以下例子都不使用 use 语句**
+
+## Init API
+
+在调用推送之前,我们必须先初始化 JPushClient,调用以下代码可以进行快速初始化:
+
+```php
+$client = new \JPush\Client($app_key, $master_secret);
+```
+
+在初始化 JPushClient 的时候,可以指定**日志路径**:
+
+```php
+$client = new \JPush\Client($app_key, $master_secret, $log_path);
+```
+> 默认日志路径为 `./jpush.log`,即保存在当前运行目录,如果想关闭日志,可以指定为 `null`。
+
+## Push API
+
+在初始化 JPushClient 后,调用以下代码将返回一个推送 Payload 构建器,它提供丰富的API来帮助你构建 PushPayload。
+
+```php
+$push = $client->push();
+```
+
+通过 [JPush Push API](https://docs.jiguang.cn/jpush/server/push/rest_api_v3_push/) 我们知道,一个 PushPayload 是由以下几个部分构成的:
+
+- Cid
+- Platform
+- Audience
+- Notification
+- Message
+- SmsContent
+- Options
+
+#### Cid
+
+```php
+$push->setCid($cid);
+```
+
+#### Platform
+
+```php
+$push->setPlatform('all');
+// OR
+$push->setPlatform('ios', 'android');
+// OR
+$push->setPlatform(['ios', 'android']);
+```
+
+#### Audience
+
+```php
+$push->addAllAudience();
+```
+
+```php
+$push->addTag('tag1');
+// OR
+$push->addTag(['tag1', 'tag2']);
+```
+
+其他诸如 `addAlias()`, `addRegistrationId()`, `addTagAnd()`, `addTagNot()`, `addSegmentId()`, `addAbtest()` 的使用方法与 `addTag()` 类似,在此不做赘述。
+
+#### Notification
+
+```php
+// 简单地给所有平台推送相同的 alert 消息
+$push->setNotificationAlert('alert');
+```
+
+**iOS Notification**
+
+```php
+// iosNotification($alert = '', array $notification = array())
+// 数组 $notification 的键支持 'sound', 'badge', 'content-available', 'mutable-content', category', 'extras', 'thread-id' 中的一个或多个
+
+// 调用示例
+$push->iosNotification();
+// OR
+$push->iosNotification('hello');
+// OR
+$push->iosNotification('hello', [
+  'sound' => 'sound',
+  'badge' => '+1',
+  'extras' => [
+    'key' => 'value'
+  ]
+]);
+```
+
+参数说明:
+
+| 参数 | 说明 |
+| --- | --- |
+| alert |表示通知内容,会覆盖上级统一指定的 alert 信息;默认内容可以为空字符串,表示不展示到通知栏, 支持字符串和数组两种形式 |
+| sound | 表示通知提示声音,默认填充为空字符串 |
+| badge | 表示应用角标,把角标数字改为指定的数字;为 0 表示清除,支持 '+1','-1' 这样的字符串,表示在原有的 badge 基础上进行增减,默认填充为 '+1' |
+| content-available | 表示推送唤醒,仅接受 true 表示为 Background Remote Notification,若不填默认表示普通的 Remote Notification |
+| mutable-content | 表示通知扩展, 仅接受 true 表示支持 iOS10 的 UNNotificationServiceExtension, 若不填默认表示普通的 Remote Notification |
+| category | IOS8才支持。设置 APNs payload 中的 'category' 字段值 |
+| thread-id	 | 表示通知分组,ios 的远程通知通过该属性来对通知进行分组,同一个 thread-id 的通知归为一组 |
+| extras | 表示扩展字段,接受一个数组,自定义 Key/value 信息以供业务使用 |
+
+**Android Notification**
+
+```php
+// androidNotification($alert = '', array $notification = array())
+// 调用示例同 IOS,数组 $notification 的键支持 'title', 'builder_id', 'priority', 'category', 'style', 'alert_type', 'big_text', 'inbox', 'big_pic_path', 'large_icon', 'intent', 'extras' 中的一个或多个
+```
+
+参数说明:
+
+| 参数 | 说明 |
+| --- | --- |
+| alert | 表示通知内容,会覆盖上级统一指定的 alert 信息;默认内容可以为空字符串,表示不展示到通知栏 |
+| title | 表示通知标题,会替换通知里原来展示 App 名称的地方 |
+| builder_id | 表示通知栏样式 ID |
+| priority | 表示通知栏展示优先级,默认为 0,范围为 -2~2 ,其他值将会被忽略而采用默认值 |
+| category | 表示通知栏条目过滤或排序,完全依赖 rom 厂商对 category 的处理策略 |
+| style | 表示通知栏样式类型,默认为 0,还有1,2,3可选,用来指定选择哪种通知栏样式,其他值无效。有三种可选分别为 bigText=1,Inbox=2,bigPicture=3 |
+| alert_type | 表示通知提醒方式, 可选范围为 -1~7 ,对应 Notification.DEFAULT_ALL = -1 或者 Notification.DEFAULT_SOUND = 1, Notification.DEFAULT_VIBRATE = 2, Notification.DEFAULT_LIGHTS = 4 的任意 “or” 组合。默认按照 -1 处理。 |
+| big_text | 表示大文本通知栏样式,当 style = 1 时可用,内容会被通知栏以大文本的形式展示出来,支持 api 16 以上的 rom |
+| inbox | 表示文本条目通知栏样式,接受一个数组,当 style = 2 时可用,数组的每个 key 对应的 value 会被当作文本条目逐条展示,支持 api 16 以上的 rom |
+| big_pic_path | 表示大图片通知栏样式,当 style = 3 时可用,可以是网络图片 url,或本地图片的 path,目前支持 .jpg 和 .png 后缀的图片。图片内容会被通知栏以大图片的形式展示出来。如果是 http/https 的 url,会自动下载;如果要指定开发者准备的本地图片就填 sdcard 的相对路径,支持 api 16 以上的 rom |
+| large_icon | 表示通知栏大图标,图标路径可以是以 http 或 https 开头的网络图片,如:"http:jiguang.cn/logo.png",图标大小不超过 30k; 也可以是位于 drawable 资源文件夹的图标路径,如:"R.drawable.lg_icon";|
+| intent | 表示扩展字段,接受一个数组,自定义 Key/value 信息以供业务使用 |
+| extras | 表示扩展字段,接受一个数组,自定义 Key/value 信息以供业务使用 |
+
+**WinPhone Notification**
+
+```php
+$push->addWinPhoneNotification($alert=null, $title=null, $_open_page=null, $extras=null)
+```
+
+参数说明:
+
+| 参数 | 说明 |
+| --- | --- |
+| alert | 表示通知内容,会覆盖上级统一指定的 alert 信息;内容为空则不展示到通知栏 |
+| title | 通知标题,会填充到 toast 类型 text1 字段上 |
+| _open_page | 点击打开的页面名称 |
+
+#### Message
+
+```php
+// message($msg_content, array $msg = array())
+// 数组 $msg 的键支持 'title', 'content_type', 'extras' 中的一个或多个
+
+// 调用示例
+$push->message('Hello JPush');
+// OR
+$push->message('Hello JPush', [
+  'title' => 'Hello',
+  'content_type' => 'text',
+  'extras' => [
+    'key' => 'value'
+  ]
+]);
+```
+
+参数说明:
+
+| 参数 | 说明 |
+| --- | --- |
+| msg_content | 消息内容本身 |
+| title | 消息标题 |
+| content_type | 消息内容类型 |
+| extras | 表示扩展字段,接受一个数组,自定义 Key/value 信息以供业务使用 |
+
+#### Sms Message
+
+```php
+$push->setSms($delay_time, $temp_id, array $temp_para = [])
+```
+
+参数说明:
+* delay_time: 表示短信发送的延迟时间,单位为秒,不能超过 24 小时(即大于等于 0 小于等于 86400)。仅对 android 平台有效。
+* temp_id: 短信补充的内容模板 ID。没有填写该字段即表示不使用短信补充功能。
+* temp_para: 短信模板中的参数
+
+##### 已弃用
+
+```php
+$push->setSmsMessage($content, $delay_time)
+```
+
+参数说明:
+* content: 短信文本,不超过 480 字符
+* delay_time: 表示短信发送的延迟时间,单位为秒,不能超过 24 小时(即大于等于 0 小于等于 86400)。仅对 android 平台有效。默认为 0,表示立即发送短信
+
+#### Options
+
+```php
+// options(array $opts = array())
+// 数组 $opts 的键支持 'sendno', 'time_to_live', 'override_msg_id', 'apns_production', 'big_push_duration', 'apns_collapse_id' 中的一个或多个
+```
+
+参数说明:
+
+| 可选项 | 说明 |
+| --- | --- |
+| sendno | 表示推送序号,纯粹用来作为 API 调用标识,API 返回时被原样返回,以方便 API 调用方匹配请求与返回 |
+| time_to_live | 表示离线消息保留时长(秒),推送当前用户不在线时,为该用户保留多长时间的离线消息,以便其上线时再次推送。默认 86400 (1 天),最长 10 天。设置为 0 表示不保留离线消息,只有推送当前在线的用户可以收到 |
+| override_msg_id | 表示要覆盖的消息ID,如果当前的推送要覆盖之前的一条推送,这里填写前一条推送的 msg_id 就会产生覆盖效果 |
+| apns_production | 表示 APNs 是否生产环境,True 表示推送生产环境,False 表示要推送开发环境;如果不指定则默认为推送开发环境 |
+| apns_collapse_id | APNs 新通知如果匹配到当前通知中心有相同 apns-collapse-id 字段的通知,则会用新通知内容来更新它,并使其置于通知中心首位;collapse id 长度不可超过 64 bytes|
+| big_push_duration | 表示定速推送时长(分钟),又名缓慢推送,把原本尽可能快的推送速度,降低下来,给定的 n 分钟内,均匀地向这次推送的目标用户推送。最大值为1400.未设置则不是定速推送 |
+
+#### Common Method
+
+```php
+// 发送推送
+// 该方法内部将自动调用构建方法获得当前构建对象,并转化为 JSON 向 JPush 服务器发送请求
+$push->send();
+```
+
+> 构建 PushPayload 的 API 每一次都会返回自身的引用,所以我们可用使用链式调用的方法提高代码的简洁性,如:
+
+```php
+$response = $push()
+    ->setCid('xxxxxx')
+    ->setPlatform(['ios', 'android'])
+    ->addTag(['tag1', 'tag2'])
+    ->setNotificationAlert('Hello, JPush')
+    ->iosNotification('hello', [
+      'sound' => 'sound',
+      'badge' => '+1',
+      'extras' => [
+        'key' => 'value'
+      ]
+    ])
+    ->androidNotification('hello')
+    ->message('Hello JPush', [
+      'title' => 'Hello',
+      'content_type' => 'text',
+      'extras' => [
+        'key' => 'value'
+      ]
+    ])
+    ->send();
+
+// OR 也可以提前准备好所有的参数,然后链式调用,这样代码可读性更好一点
+$cid = 'xxxxxx';
+$platform = array('ios', 'android');
+$alert = 'Hello JPush';
+$tag = array('tag1', 'tag2');
+$regId = array('rid1', 'rid2');
+$ios_notification = array(
+    'sound' => 'hello jpush',
+    'badge' => 2,
+    'content-available' => true,
+    'category' => 'jiguang',
+    'extras' => array(
+        'key' => 'value',
+        'jiguang'
+    ),
+);
+$android_notification = array(
+    'title' => 'hello jpush',
+    'builder_id' => 2,
+    'extras' => array(
+        'key' => 'value',
+        'jiguang'
+    ),
+);
+$content = 'Hello World';
+$message = array(
+    'title' => 'hello jpush',
+    'content_type' => 'text',
+    'extras' => array(
+        'key' => 'value',
+        'jiguang'
+    ),
+);
+$options = array(
+    'sendno' => 100,
+    'time_to_live' => 100,
+    'override_msg_id' => 100,
+    'big_push_duration' => 100
+);
+$response = $push->setCid($cid)
+    ->setPlatform($platform)
+    ->addTag($tag)
+    ->addRegistrationId($regId)
+    ->iosNotification($alert, $ios_notification)
+    ->androidNotification($alert, $android_notification)
+    ->message($content, $message)
+    ->options($options)
+    ->send();
+```
+
+#### 获取 Cid
+
+```php
+$push->getCid($count = 1, $type = 'push');
+```
+
+## Report API
+
+```php
+ $report = $client->report();
+ ```
+
+#### 获取送达统计
+
+```php
+$report->getReceived('msg_id');
+// OR
+$report->getReceived(['msg_id1', 'msg_id2']);
+```
+
+#### 送达状态查询
+
+```php
+$msg_id0 = 66666666666;
+$report->getMessageStatus($msg_id0, 'rid0');
+# OR
+$report->getMessageStatus($msg_id0, ['rid0', 'rid1']);
+#OR
+$report->getMessageStatus($msg_id0, ['rid0', 'rid1'], '2017-12-21');
+```
+
+#### 获取消息统计
+
+```php
+// getMessages(getMessages($msgIds));
+// 消息统计与送达统计一样,接受一个数组的参数,在这里不做赘述
+```
+
+#### 获取用户统计
+
+调用一下代码可以获得用户统计
+
+```php
+$report->getUsers($time_unit, $start, $duration)
+```
+
+参数说明:
+
+- time_unit:`String` 时间单位, 可取值HOUR, DAY, MONTH
+- start:`String` 起始时间
+    - 如果单位是小时,则起始时间是小时(包含天),格式例:2014-06-11 09
+    - 如果单位是天,则起始时间是日期(天),格式例:2014-06-11
+    - 如果单位是月,则起始时间是日期(月),格式例:2014-06
+- duration:`String` 持续时长
+    - 如果单位是天,则是持续的天数。以此类推
+    - 只支持查询60天以内的用户信息,对于time_unit为HOUR的,只支持输出当天的统计结果。
+
+## Device API
+
+```php
+$device = $client->device();
+```
+
+#### 操作 Device(registration_id)
+
+```php
+// 查询指定设备的别名与标签
+$device->getDevices($registration_id);
+
+
+// 更新指定设备的别名与标签
+
+// 更新 Alias
+$device->updateAlias($registration_id, 'alias');
+// 添加 tag, 支持字符串和数组两种参数
+$device->addTags($registration_id, 'tag');
+// OR
+$device->addTags($registration_id, ['tag1', 'tag2']);
+// 移除 tag,支持字符串和数组两种参数
+$device->removeTags($registration_id, 'tags');
+// OR
+$device->removeTags($registration_id,  ['tag1', 'tag2']);
+// 清空所有 tag
+$device->clearTags($registration_id);
+
+// 更新 mobile
+$device->updateMoblie($registration_id, '13800138000');
+// 取消手机绑定
+$device->clearMobile($registration_id);
+
+// getDevicesStatus($registrationId)
+// 获取在线用户的登录状态(VIP专属接口),支持字符串和数组两种参数
+$device->getDevicesStatus('rid');
+// OR
+$device->getDevicesStatus(['rid1', 'rid2']);
+```
+
+#### 操作标签
+
+```php
+// 获取标签列表
+$device->getTags()
+
+// 判断指定设备是否在指定标签之下
+$device->isDeviceInTag($registrationId, $tag);
+
+
+// 更新标签
+
+// 为标签添加设备,支持字符串和数组两种参数
+$device->addDevicesToTag($tag, 'rid');
+$device->addDevicesToTag($tag, ['rid1', 'rid2']);
+
+// 为标签移除设备,支持字符串和数组两种参数
+$device->removeDevicesFromTag($tag, 'rid');
+$device->removeDevicesFromTag($tag, ['rid1', 'rid2']);
+
+
+// 删除标签
+$device->deleteTag('tag');
+```
+
+#### 操作别名
+
+```php
+// 获取指定别名下的设备
+$device->getAliasDevices('alias');
+
+// 删除别名
+$device->deleteAlias('alias');
+```
+
+## Schedule API
+
+```php
+$schedule = $client->schedule();
+```
+
+#### 创建定时任务
+
+定时任务分为Single与Periodical两种,可以通过调用以下方法创建定时任务
+
+```php
+$schedule->createSingleSchedule($name, $push_payload, $trigger)
+$schedule->createPeriodicalSchedule($name, $push_payload, $trigger)
+```
+
+参数说明:
+- name: `String` 定时任务的名称
+- push_payload: `PushPayload` Push的构建对象,通过Push模块的`build()`方法获得
+- trigger: `Array` 触发器对象
+
+#### 更新定时任务
+
+```php
+$schedule->updateSingleSchedule($schedule_id, $name=null, $enabled=null, $push_payload=null, $trigger=null)
+$schedule->updatePeriodicalSchedule($schedule_id, $name=null, $enabled=null, $push_payload=null, $trigger=null)
+```
+
+#### 其他
+
+```php
+// 获取定时任务列表
+$schedule->getSchedules($page=1);
+
+// 获取指定定时任务
+$schedule->getSchedule($schedule_id);
+
+// 删除指定定时任务
+$schedule->deleteSchedule($schedule_id);
+
+// 获取定时任务对应的所有 msg_id
+$schedule->getMsgIds($schedule_id);
+```
+
+## Exception Handle
+
+当 API 请求发生错误时,SDK 将抛出异常,Pushpayload 具体错误代码请参考[ API 错误代码表](https://docs.jiguang.cn/jpush/server/push/rest_api_v3_push/#_19)。
+PHP SDK 主要抛出两个异常 `\JPush\Exceptions\APIConnectionException` 和 `\JPush\Exceptions\APIRequestException` 分别对应请求连接产生的异常和请求响应的异常。
+这两种异常都需要捕获,为简单起见,也可以捕获他们的父类异常 `JPush\Exceptions\JPushException`(见 README)。另外 APIRequestException 异常还提供其他方法供开发者调用。
+
+```php
+try {
+    $pusher->send();
+} catch (\JPush\Exceptions\APIConnectionException $e) {
+    // try something here
+    print $e;
+} catch (\JPush\Exceptions\APIRequestException $e) {
+    // try something here
+    print $e;
+}
+```

+ 28 - 0
vendor/jpush/jpush/doc/grouppush.md

@@ -0,0 +1,28 @@
+# JPush Group Push
+
+## 获取 Group Key 和 Group Master Secret
+
+```php
+$group_key = 'xxxx';
+$group_master_secret = 'xxxx';
+```
+
+##  初始化
+
+**注:Group Key 需拼接 'group-' 使用**
+
+```php
+$client = new \JPush\Client('group-' . $group_key, $group_master_secret);
+```
+
+## 简单群组推送
+
+```php
+$client->push()
+    ->setPlatform('all')
+    ->addAllAudience()
+    ->setNotificationAlert('Hello, JPush')
+    ->send();
+```
+
+> [Example](https://github.com/jpush/jpush-api-php-client/blob/master/examples/push_example.php)

+ 56 - 0
vendor/jpush/jpush/doc/http2.md

@@ -0,0 +1,56 @@
+# JPush API PHP Client With HTTP/2 Support
+
+> JPush API PHP Client 全面支持 HTTP/2,
+> **要求 PHP >= 5.5.24**,
+> 但由于 libcurl 对于 HTTP/2 的实现依赖于第三方库 [nghttp2](https://github.com/nghttp2/nghttp2) 所以如果要支持 HTTP/2 需要做一些其他的配置。
+
+### 安装 nghttp2
+
+系统依赖仅针对 Ubuntu 14.04 LTS (trusty) 和 Debian 7.0 (wheezy) 或以上版本,其他系统版本请按照 nghttp2 的文档来操作:
+
+> From Ubuntu 15.10, spdylay has been available as a package named libspdylay-dev. For the earlier Ubuntu release, you need to build it yourself: http://tatsuhiro-t.github.io/spdylay/
+
+详细情况请查看 [nghttp2 的文档](https://github.com/nghttp2/nghttp2#requirements)。
+
+```bash
+# Get build requirements
+# Some of these are used for the Python bindings
+# this package also installs
+$ sudo apt-get install g++ make binutils autoconf automake autotools-dev libtool pkg-config \
+  zlib1g-dev libcunit1-dev libssl-dev libxml2-dev libev-dev libevent-dev libjansson-dev \
+  libjemalloc-dev cython python3-dev python-setuptools
+
+# Build nghttp2 from source
+$ git clone https://github.com/tatsuhiro-t/nghttp2.git
+$ cd nghttp2
+$ autoreconf -i
+$ automake
+$ autoconf
+$ ./configure
+$ make
+$ sudo make install
+```
+
+### 升级 curl 至最新版本
+
+```bash
+$ sudo apt-get build-dep curl
+# 请根据当前的 curl 官网中的最新版本(https://curl.haxx.se/download/)替换下面的相应位置
+$ wget https://curl.haxx.se/download/curl-7.x.x.tar.bz2
+$ tar -xvjf curl-7.x.x.tar.bz2
+$ cd curl-7.x.x
+$ ./configure --with-nghttp2=/usr/local --with-ssl
+$ make
+$ sudo make install
+```
+
+### 测试
+
+##### 命令行测试
+命令行运行 `$ curl --version`,若输出中的 Features 栏中有 `HTTP2` 一项则证明配置成功。
+
+##### 样例测试
+运行样例 `$ php examples/devices/get_devices_example.php`,若输出中的 HTTP 版本是 HTTP/2 则证明已经在使用 HTTP2 发送请求和接受响应了。
+
+##### 测试测试
+运行测试 `$./vendor/bin/phpunit tests/JPush/DevicePayloadTest.php`,若打印出的 http headers 中的 HTTP 版本是 HTTP/2 则证明已经在使用 HTTP2 发送请求和接受响应了。

+ 14 - 0
vendor/jpush/jpush/examples/admin_example.php

@@ -0,0 +1,14 @@
+<?php
+// 这只是使用样例,不应该直接用于实际生产环境中 !!
+
+require 'config.php';
+
+use JPush\AdminClient as Admin;
+
+$admin = new Admin($dev_key, $dev_secret);
+$response = $admin->createApp('aaa', 'cn.jpush.app');
+print_r($response);
+
+$appKey = $response['body']['app_key'];
+$response = $admin->deleteApp($appKey);
+print_r($response);

+ 35 - 0
vendor/jpush/jpush/examples/batch_push_example.php

@@ -0,0 +1,35 @@
+<?php
+// 这只是使用样例,不应该直接用于实际生产环境中 !!
+
+require 'config.php';
+
+$singlePayloads = array(
+    array(
+        'platform' => 'all',
+        'target' => 'regid1',
+        'notification' => array(
+           'alert' => 'NotificationAlert1'
+        )
+    ),
+    array(
+        'platform' => 'all',
+        'target' => 'regid2',
+        'notification' => array(
+           'alert' => 'NotificationAlert2'
+        )
+    )
+);
+
+$push_payload = $client -> push();
+try {
+    $response = $push_payload -> batchPushByRegid($singlePayloads);
+    print_r($response);
+    $response = $push_payload -> batchPushByAlias($singlePayloads);
+    print_r($response);
+} catch (\JPush\Exceptions\APIConnectionException $e) {
+    // try something here
+    print $e;
+} catch (\JPush\Exceptions\APIRequestException $e) {
+    // try something here
+    print $e;
+}

+ 7 - 0
vendor/jpush/jpush/examples/cid_example.php

@@ -0,0 +1,7 @@
+<?php
+
+require 'config.php';
+
+$response = $client->push()->getCid();
+
+print_r($response);

+ 10 - 0
vendor/jpush/jpush/examples/config.php.example

@@ -0,0 +1,10 @@
+<?php
+require __DIR__ . '/../autoload.php';
+
+use JPush\Client as JPush;
+
+$app_key = getenv('app_key');
+$master_secret = getenv('master_secret');
+$registration_id = getenv('registration_id');
+
+$client = new JPush($app_key, $master_secret);

+ 5 - 0
vendor/jpush/jpush/examples/devices/delete_alias_example.php

@@ -0,0 +1,5 @@
+<?php
+require __DIR__ . '/../config.php';
+
+$response = $client->device()->deleteAlias('alias');
+print_r($response);

+ 5 - 0
vendor/jpush/jpush/examples/devices/delete_tag_example.php

@@ -0,0 +1,5 @@
+<?php
+require __DIR__ . '/../config.php';
+
+$response = $client->device()->deleteTag('tag');
+print_r($response);

+ 6 - 0
vendor/jpush/jpush/examples/devices/get_alias_devices_example.php

@@ -0,0 +1,6 @@
+<?php
+require __DIR__ . '/../config.php';
+
+// 更新 Alias
+$response = $client->device()->getAliasDevices('alias');
+print_r($response);

+ 6 - 0
vendor/jpush/jpush/examples/devices/get_devices_example.php

@@ -0,0 +1,6 @@
+<?php
+require __DIR__ . '/../config.php';
+
+// 获取指定设备的 Mobile,Alias,Tags 等信息
+$response = $client->device()->getDevices($registration_id);
+print_r($response);

+ 13 - 0
vendor/jpush/jpush/examples/devices/get_devices_status_example.php

@@ -0,0 +1,13 @@
+<?php
+require __DIR__ . '/../config.php';
+
+// 获取用户在线状态(VIP专属接口)
+try {
+    $response = $client->device()->getDevicesStatus($registration_id);
+} catch(\JPush\Exceptions\APIRequestException $e) {
+    print $e;
+    print $e->getHttpCode();
+    print $e->getHeaders();
+}
+
+print_r($response);

+ 6 - 0
vendor/jpush/jpush/examples/devices/get_tags_example.php

@@ -0,0 +1,6 @@
+<?php
+require __DIR__ . '/../config.php';
+
+// 获取Tag列表
+$response = $client->device()->getDevices($registration_id);
+print_r($response);

+ 56 - 0
vendor/jpush/jpush/examples/devices/update_device_example.php

@@ -0,0 +1,56 @@
+<?php
+require __DIR__ . '/../config.php';
+
+// 更新 Alias
+$result = $client->device()->getDevices($registration_id);
+print "before update alias = " . $result['body']['alias'] . "\n";
+
+print 'updating alias ... response = ';
+$response = $client->device()->updateAlias($registration_id, 'jpush_alias');
+print_r($response);
+
+$result = $client->device()->getDevices($registration_id);
+print "after update alias = " . $result['body']['alias'] . "\n\n";
+
+// 添加 tag
+$result = $client->device()->getDevices($registration_id);
+print "before add tags = [" . implode(',', $result['body']['tags']) . "]\n";
+
+print 'add tag1 tag2 ... response = ';
+
+$response = $client->device()->addTags($registration_id, 'tag0');
+print_r($response);
+
+$response = $client->device()->addTags($registration_id, ['tag1', 'tag2']);
+print_r($response);
+
+$result = $client->device()->getDevices($registration_id);
+print "after add tags = [" . implode(',', $result['body']['tags']) . "]\n\n";
+
+
+// 移除 tag
+$result = $client->device()->getDevices($registration_id);
+print "before remove tags = [" . implode(',', $result['body']['tags']) . "]\n";
+
+print 'removing tag1 tag2 ...  response = ';
+
+$response = $client->device()->removeTags($registration_id, 'tag0');
+print_r($response);
+
+$response = $client->device()->removeTags($registration_id, ['tag1', 'tag2']);
+print_r($response);
+
+$result = $client->device()->getDevices($registration_id);
+print "after remove tags = [" . implode(',', $result['body']['tags']) . "]\n\n";
+
+
+// 更新 mobile
+$result = $client->device()->getDevices($registration_id);
+print "before update mobile = " . $result['body']['mobile'] . "\n";
+
+print 'updating mobile ... response = ';
+$response = $client->device()->updateMoblie($registration_id, '13800138000');
+print_r($response);
+
+$result = $client->device()->getDevices($registration_id);
+print "after update mobile = " . $result['body']['mobile'] . "\n\n";

+ 29 - 0
vendor/jpush/jpush/examples/devices/update_tag_example.php

@@ -0,0 +1,29 @@
+<?php
+require __DIR__ . '/../config.php';
+
+// 为一个标签添加设备
+$result = $client->device()->isDeviceInTag($registration_id, 'tag');
+$r = $result['body']['result'] ? 'true' : 'false';
+print "before add device = " . $r . "\n";
+
+print 'adding device ... response = ';
+$response = $client->device()->addDevicesToTag('tag', $registration_id);
+print_r($response);
+
+$result = $client->device()->isDeviceInTag($registration_id, 'tag');
+$r = $result['body']['result'] ? 'true' : 'false';
+print "after add tags = " . $r . "\n\n";
+
+// 为一个标签删除设备
+$result = $client->device()->isDeviceInTag($registration_id, 'tag');
+$r = $result['body']['result'] ? 'true' : 'false';
+print "before remove device = " . $r . "\n";
+
+print 'removing device ...  response = ';
+$response = $client->device()->removeDevicesFromTag('tag', $registration_id);
+print_r($response);
+
+$result = $client->device()->isDeviceInTag($registration_id, 'tag');
+$r = $result['body']['result'] ? 'true' : 'false';
+print "after remove device = " . $r . "\n\n";
+

+ 24 - 0
vendor/jpush/jpush/examples/grouppush_example.php

@@ -0,0 +1,24 @@
+<?php
+require __DIR__ . '/../autoload.php';
+
+use JPush\Client as JPush;
+
+$group_key = 'xxxx';
+$group_master_secret = 'xxxx';
+
+$client = new JPush('group-' . $group_key, $group_master_secret, null);
+
+$push_payload = $client->push()
+    ->setPlatform('all')
+    ->addAllAudience()
+    ->setNotificationAlert('Hi, JPush');
+try {
+    $response = $push_payload->send();
+    print_r($response);
+} catch (\JPush\Exceptions\APIConnectionException $e) {
+    // try something here
+    print $e;
+} catch (\JPush\Exceptions\APIRequestException $e) {
+    // try something here
+    print $e;
+}

+ 36 - 0
vendor/jpush/jpush/examples/huawei_push_example.php

@@ -0,0 +1,36 @@
+<?php
+// 这只是使用样例,不应该直接用于实际生产环境中 !!
+
+require 'config.php';
+
+try {
+    $payload = $client->push()
+        ->setPlatform(array('ios', 'android'))
+        // ->addAlias('alias')
+        ->addTag(array('tag1', 'tag2'))
+        // ->addRegistrationId($registration_id)
+        ->setNotificationAlert('Hi, JPush')
+        ->androidNotification('Hello HUAWEI', array(
+            'title' => 'huawei demo',
+
+            // ---------------------------------------------------
+            // `uri_activity` 字段用于指定想要打开的 activity.
+            // 值为 activity 节点的 “android:name” 属性值。
+            'uri_activity' => 'cn.jpush.android.ui.OpenClickActivity',
+            // ---------------------------------------------------
+
+            'extras' => array(
+                'key' => 'value',
+                'jiguang'
+            ),
+        ));
+        // ->send();
+        print_r($payload->build());
+
+} catch (\JPush\Exceptions\APIConnectionException $e) {
+    // try something here
+    print $e;
+} catch (\JPush\Exceptions\APIRequestException $e) {
+    // try something here
+    print $e;
+}

+ 140 - 0
vendor/jpush/jpush/examples/push_example.php

@@ -0,0 +1,140 @@
+<?php
+// 这只是使用样例,不应该直接用于实际生产环境中 !!
+
+require __DIR__ . '/../autoload.php';
+
+use JPush\Client as JPush;
+
+// 这里填写appKey,masterSecret以及registration_id
+$app_key = 'e5c0d34f58732cf09b2d4d74';
+$master_secret = '4cdda6d3c8b029941dbc5cb3';
+$registration_id = ('registration_id');
+
+$client = new JPush($app_key, $master_secret);
+
+// 简单推送示例
+// 这只是使用样例,不应该直接用于实际生产环境中 !!
+
+// $push_payload = $client->push()
+//     ->setPlatform('all')
+//     ->addAllAudience()
+//     ->setNotificationAlert('Hi, JPush');
+// try {
+//     $response = $push_payload->send();
+//     print_r($response);
+// } catch (\JPush\Exceptions\APIConnectionException $e) {
+//     // try something here
+//     print $e;
+// } catch (\JPush\Exceptions\APIRequestException $e) {
+//     // try something here
+//     print $e;
+// }
+
+// 完整的推送示例
+// 这只是使用样例,不应该直接用于实际生产环境中 !!
+try {
+    $response = $client->push()
+        ->setPlatform(array('ios', 'android'))
+        // 一般情况下,关于 audience 的设置只需要调用 addAlias、addTag、addTagAnd  或 addRegistrationId
+        // 这四个方法中的某一个即可,这里仅作为示例,当然全部调用也可以,多项 audience 调用表示其结果的交集
+        // 即是说一般情况下,下面三个方法和没有列出的 addTagAnd 一共四个,只适用一个便可满足大多数的场景需求
+
+        // ->addAlias('alias')
+        // ->addTag(array('tag1', 'tag2'))
+        // ->addRegistrationId($registration_id)
+        ->addAllAudience()
+
+        ->setNotificationAlert('Test custom')
+        ->iosNotification('Hello IOS', array(
+            'sound' => 'sound.caf',
+            // 'badge' => '+1',
+            // 'content-available' => true,
+            // 'mutable-content' => true,
+            'category' => 'jiguang',
+            'extras' => array(
+                'key' => 'value',
+                'jiguang'
+            ),
+        ))
+        ->androidNotification('Hello Android', array(
+            'title' => 'hello jpush',
+            // 'builder_id' => 2,
+            'extras' => array(
+                'key' => 'value',
+                'jiguang'
+            ),
+        ))
+        // voip可以传输任意键值对,可用作自定义
+        ->voip(array(
+            'test123' => 'val1',
+            'jsontest' => 2,
+            'booleantest' => true
+        ))
+        ->message('message content', array(
+            'title' => 'hello jpush',
+            // 'content_type' => 'text',
+            'extras' => array(
+                'key' => 'value',
+                'jiguang'
+            ),
+        ))
+        ->options(array(
+            // sendno: 表示推送序号,纯粹用来作为 API 调用标识,
+            // API 返回时被原样返回,以方便 API 调用方匹配请求与返回
+            // 这里设置为 100 仅作为示例
+
+            // 'sendno' => 100,
+
+            // time_to_live: 表示离线消息保留时长(秒),
+            // 推送当前用户不在线时,为该用户保留多长时间的离线消息,以便其上线时再次推送。
+            // 默认 86400 (1 天),最长 10 天。设置为 0 表示不保留离线消息,只有推送当前在线的用户可以收到
+            // 这里设置为 1 仅作为示例
+
+            'time_to_live' => 1,
+
+            // apns_production: 表示APNs是否生产环境,
+            // True 表示推送生产环境,False 表示要推送开发环境;如果不指定则默认为推送开发环境
+
+            // 'apns_production' => false,
+
+            // big_push_duration: 表示定速推送时长(分钟),又名缓慢推送,把原本尽可能快的推送速度,降低下来,
+            // 给定的 n 分钟内,均匀地向这次推送的目标用户推送。最大值为1400.未设置则不是定速推送
+            // 这里设置为 1 仅作为示例
+
+            // 'big_push_duration' => 1
+        ))
+        ->setSmsMessage(array(
+            'delay_time' => 60,
+            'signid' => 154,
+            'temp_id' => 1,
+            'temp_para' => array(
+                'code' => 357
+            ),
+            'active_filter' => false
+        ))
+        // custom可自定义最外层参数,如skd未支持部分文档功能,用户可自行写入
+        // 这里仅作为例子展示
+        // ->custom(array(
+        //     'sms_message' => array(
+        //         'active_filter' => false,
+        //         'delay_time' => 60,
+        //         'signid' => 154,
+        //         'temp_id' => 1,
+        //         'temp_para' => array(
+        //             'code' => 357
+        //         )),
+        //     'options' => array(
+        //         'apns_production' => false,
+        //         'time_to_live' => 62000,
+        //     )
+        // ))
+        ->send();
+        print_r($response);
+
+} catch (\JPush\Exceptions\APIConnectionException $e) {
+    // try something here
+    print $e;
+} catch (\JPush\Exceptions\APIRequestException $e) {
+    // try something here
+    print $e;
+}

+ 5 - 0
vendor/jpush/jpush/examples/reports/messages_detail_example.php

@@ -0,0 +1,5 @@
+<?php
+require __DIR__ . '/../config.php';
+
+$result = $client->report()->getMessagesDetail('149646415212');
+print_r($result);

+ 5 - 0
vendor/jpush/jpush/examples/reports/received_detail_example.php

@@ -0,0 +1,5 @@
+<?php
+require __DIR__ . '/../config.php';
+
+$result = $client->report()->getReceivedDetail('149646415212');
+print_r($result);

+ 26 - 0
vendor/jpush/jpush/examples/schedule_example.php

@@ -0,0 +1,26 @@
+<?php
+// 这只是使用样例不应该直接用于实际生产环境中 !!
+
+require 'config.php';
+
+$payload = $client->push()
+    ->setPlatform("all")
+    ->addAllAudience()
+    ->setNotificationAlert("Hi, 这是一条定时发送的消息")
+    ->build();
+
+// 创建一个2016-12-22 13:45:00触发的定时任务
+$response = $client->schedule()->createSingleSchedule("每天14点发送的定时任务", $payload, array("time"=>"2016-12-22 13:45:00"));
+print_r($response);
+
+// 创建一个每天14点发送的定时任务
+$response = $client->schedule()->createPeriodicalSchedule("每天14点发送的定时任务", $payload,
+        array(
+            "start"=>"2016-12-22 13:45:00",
+            "end"=>"2016-12-25 13:45:00",
+            "time"=>"14:00:00",
+            "time_unit"=>"DAY",
+            "frequency"=>1
+        ));
+print_r($response);
+

+ 24 - 0
vendor/jpush/jpush/examples/zone_examples.php

@@ -0,0 +1,24 @@
+<?php
+// 这只是使用样例,不应该直接用于实际生产环境中 !!
+
+require 'config.php';
+use JPush\Client as JPush;
+
+// 简单推送示例
+// 这只是使用样例,不应该直接用于实际生产环境中 !!
+$client = new JPush($app_key, $master_secret, null, null, 'BJ');
+
+$push_payload = $client->push()
+    ->setPlatform('all')
+    ->addAllAudience()
+    ->setNotificationAlert('Hi, JPush');
+try {
+    $response = $push_payload->send();
+    print_r($response);
+} catch (\JPush\Exceptions\APIConnectionException $e) {
+    // try something here
+    print $e;
+} catch (\JPush\Exceptions\APIRequestException $e) {
+    // try something here
+    print $e;
+}

+ 15 - 0
vendor/jpush/jpush/phpunit.xml.dist

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit
+    colors="true"
+    convertErrorsToExceptions="true"
+    convertNoticesToExceptions="true"
+    convertWarningsToExceptions="true"
+    stopOnFailure="false"
+    syntaxCheck="true"
+    bootstrap="tests/bootstrap.php">
+    <testsuites>
+        <testsuite name="JPush PHP SDK Test Suite">
+            <directory>tests/JPush</directory>
+        </testsuite>
+    </testsuites>
+</phpunit>

+ 42 - 0
vendor/jpush/jpush/src/JPush/AdminClient.php

@@ -0,0 +1,42 @@
+<?php
+namespace JPush;
+
+class AdminClient {
+
+    const ADMIN_URL = 'https://admin.jpush.cn/v1/app/';
+
+    private $devKey;
+    private $devSecret;
+    private $retryTimes;
+    private $logFile;
+
+    function __construct($devKey, $devSecret) {
+        if (!is_string($devKey) || !is_string($devSecret)) {
+            throw new InvalidArgumentException("Invalid devKey or devSecret");
+        }
+        $this->devKey = $devKey;
+        $this->devSecret = $devSecret;
+        $this->retryTimes = 1;
+        $this->logFile = null;
+    }
+
+    public function getAuthStr() { return $this->devKey . ":" . $this->devSecret; }
+    public function getRetryTimes() { return $this->retryTimes; }
+    public function getLogFile() { return $this->logFile; }
+
+    public function createApp($appName, $androidPackage, $groupName=null) {
+        $url = AdminClient::ADMIN_URL;
+        $body = [
+            'app_name' => $appName,
+            'android_package'=> $androidPackage,
+            'group_name' => $groupName
+
+        ];
+        return Http::post($this, $url, $body);
+    }
+
+    public function deleteApp($appKey) {
+        $url = AdminClient::ADMIN_URL . $appKey . '/delete';
+        return Http::post($this, $url, []);
+    }
+}

+ 71 - 0
vendor/jpush/jpush/src/JPush/Client.php

@@ -0,0 +1,71 @@
+<?php
+namespace JPush;
+use InvalidArgumentException;
+
+class Client {
+
+    private $appKey;
+    private $masterSecret;
+    private $retryTimes;
+    private $logFile;
+    private $zone;
+    private static $zones = [
+        'DEFAULT' => [
+            'push' => 'https://api.jpush.cn/v3/',
+            'report' => 'https://report.jpush.cn/v3/',
+            'device' => 'https://device.jpush.cn/v3/devices/',
+            'alias' => 'https://device.jpush.cn/v3/aliases/',
+            'tag' => 'https://device.jpush.cn/v3/tags/',
+            'schedule' => 'https://api.jpush.cn/v3/schedules'
+        ],
+        'BJ' => [
+            'push'      => 'https://bjapi.push.jiguang.cn/v3/',
+            'report'    => 'https://bjapi.push.jiguang.cn/v3/report/',
+            'device'    => 'https://bjapi.push.jiguang.cn/v3/device/',
+            'alias'     => 'https://bjapi.push.jiguang.cn/v3/device/aliases/',
+            'tag'       => 'https://bjapi.push.jiguang.cn/v3/device/tags/',
+            'schedules' => 'https://bjapi.push.jiguang.cn/v3/push/schedules'
+        ]
+    ];
+
+    public function __construct($appKey, $masterSecret, $logFile=Config::DEFAULT_LOG_FILE, $retryTimes=Config::DEFAULT_MAX_RETRY_TIMES, $zone = null) {
+        if (!is_string($appKey) || !is_string($masterSecret)) {
+            throw new InvalidArgumentException("Invalid appKey or masterSecret");
+        }
+        $this->appKey = $appKey;
+        $this->masterSecret = $masterSecret;
+        if (!is_null($retryTimes)) {
+            $this->retryTimes = $retryTimes;
+        } else {
+            $this->retryTimes = 1;
+        }
+        $this->logFile = $logFile;
+        if (!is_null($zone) && in_array(strtoupper($zone), array_keys(self::$zones))) {
+            $this->zone = strtoupper($zone);
+        } else {
+            $this->zone = null;
+        }
+    }
+
+    public function push() { return new PushPayload($this); }
+    public function report() { return new ReportPayload($this); }
+    public function device() { return new DevicePayload($this); }
+    public function schedule() { return new SchedulePayload($this);}
+
+    public function getAuthStr() { return $this->appKey . ":" . $this->masterSecret; }
+    public function getRetryTimes() { return $this->retryTimes; }
+    public function getLogFile() { return $this->logFile; }
+
+    public function is_group() {
+        $str = substr($this->appKey, 0, 6);
+        return $str === 'group-';
+    }
+
+    public function makeURL($key) {
+        if (is_null($this->zone)) {
+            return self::$zones['DEFAULT'][$key];
+        } else {
+            return self::$zones[$this->zone][$key];
+        }
+    }
+}

+ 16 - 0
vendor/jpush/jpush/src/JPush/Config.php

@@ -0,0 +1,16 @@
+<?php
+namespace JPush;
+
+class Config {
+    const DISABLE_SOUND = "_disable_Sound";
+    const DISABLE_BADGE = 0x10000;
+    const USER_AGENT = 'JPush-API-PHP-Client';
+    const CONNECT_TIMEOUT = 20;
+    const READ_TIMEOUT = 120;
+    const DEFAULT_MAX_RETRY_TIMES = 3;
+    const DEFAULT_LOG_FILE = "./jpush.log";
+    const HTTP_GET = 'GET';
+    const HTTP_POST = 'POST';
+    const HTTP_DELETE = 'DELETE';
+    const HTTP_PUT = 'PUT';
+}

+ 224 - 0
vendor/jpush/jpush/src/JPush/DevicePayload.php

@@ -0,0 +1,224 @@
+<?php
+namespace JPush;
+use InvalidArgumentException;
+
+class DevicePayload {
+    private $client;
+
+    /**
+     * DevicePayload constructor.
+     * @param $client JPush
+     */
+    public function __construct($client)
+    {
+        $this->client = $client;
+    }
+
+    public function getDevices($registrationId) {
+        $url = $this->client->makeURL('device') . $registrationId;
+        return Http::get($this->client, $url);
+    }
+
+    public function updateAlias($registration_id, $alias) {
+        return $this->updateDevice($registration_id, $alias);
+    }
+    public function addTags($registration_id, $tags) {
+        $tags = is_array($tags) ? $tags : array($tags);
+        return $this->updateDevice($registration_id, null, null, $tags);
+    }
+    public function removeTags($registration_id, $tags) {
+        $tags = is_array($tags) ? $tags : array($tags);
+        return $this->updateDevice($registration_id, null, null, null, $tags);
+    }
+    public function updateMoblie($registration_id, $mobile) {
+        return $this->updateDevice($registration_id, null, $mobile);
+    }
+
+    public function clearMobile($registrationId) {
+        $url = $this->client->makeURL('device') . $registrationId;
+        return Http::post($this->client, $url, ['mobile' => '']);
+    }
+
+    public function clearTags($registrationId) {
+        $url = $this->client->makeURL('device') . $registrationId;
+        return Http::post($this->client, $url, ['tags' => '']);
+    }
+
+    public function updateDevice($registrationId, $alias = null, $mobile = null, $addTags = null, $removeTags = null) {
+        $payload = array();
+        if (!is_string($registrationId)) {
+            throw new InvalidArgumentException('Invalid registration_id');
+        }
+
+        $aliasIsNull = is_null($alias);
+        $mobileIsNull = is_null($mobile);
+        $addTagsIsNull = is_null($addTags);
+        $removeTagsIsNull = is_null($removeTags);
+
+        if ($aliasIsNull && $addTagsIsNull && $removeTagsIsNull && $mobileIsNull) {
+            throw new InvalidArgumentException("alias, addTags, removeTags not all null");
+        }
+
+        if (!$aliasIsNull) {
+            if (is_string($alias)) {
+                $payload['alias'] = $alias;
+            } else {
+                throw new InvalidArgumentException("Invalid alias string");
+            }
+        }
+
+        if (!$mobileIsNull) {
+            if (is_string($mobile)) {
+                $payload['mobile'] = $mobile;
+            } else {
+                throw new InvalidArgumentException("Invalid mobile string");
+            }
+        }
+
+        $tags = array();
+
+        if (!$addTagsIsNull) {
+            if (is_array($addTags)) {
+                $tags['add'] = $addTags;
+            } else {
+                throw new InvalidArgumentException("Invalid addTags array");
+            }
+        }
+
+        if (!$removeTagsIsNull) {
+            if (is_array($removeTags)) {
+                $tags['remove'] = $removeTags;
+            } else {
+                throw new InvalidArgumentException("Invalid removeTags array");
+            }
+        }
+
+        if (count($tags) > 0) {
+            $payload['tags'] = $tags;
+        }
+
+        $url = $this->client->makeURL('device') . $registrationId;
+        return Http::post($this->client, $url, $payload);
+    }
+
+    public function getTags() {
+        $url = $this->client->makeURL('tag');
+        return Http::get($this->client, $url);
+    }
+
+    public function isDeviceInTag($registrationId, $tag) {
+        if (!is_string($registrationId)) {
+            throw new InvalidArgumentException("Invalid registration_id");
+        }
+
+        if (!is_string($tag)) {
+            throw new InvalidArgumentException("Invalid tag");
+        }
+        $url = $this->client->makeURL('tag') . $tag . '/registration_ids/' . $registrationId;
+        return Http::get($this->client, $url);
+    }
+
+    public function addDevicesToTag($tag, $addDevices) {
+        $device = is_array($addDevices) ? $addDevices : array($addDevices);
+        return $this->updateTag($tag, $device, null);
+    }
+    public function removeDevicesFromTag($tag, $removeDevices) {
+        $device = is_array($removeDevices) ? $removeDevices : array($removeDevices);
+        return $this->updateTag($tag, null, $device);
+    }
+    public function updateTag($tag, $addDevices = null, $removeDevices = null) {
+        if (!is_string($tag)) {
+            throw new InvalidArgumentException("Invalid tag");
+        }
+
+        $addDevicesIsNull = is_null($addDevices);
+        $removeDevicesIsNull = is_null($removeDevices);
+
+        if ($addDevicesIsNull && $removeDevicesIsNull) {
+            throw new InvalidArgumentException("Either or both addDevices and removeDevices must be set.");
+        }
+
+        $registrationId = array();
+
+        if (!$addDevicesIsNull) {
+            if (is_array($addDevices)) {
+                $registrationId['add'] = $addDevices;
+            } else {
+                throw new InvalidArgumentException("Invalid addDevices");
+            }
+        }
+
+        if (!$removeDevicesIsNull) {
+            if (is_array($removeDevices)) {
+                $registrationId['remove'] = $removeDevices;
+            } else {
+                throw new InvalidArgumentException("Invalid removeDevices");
+            }
+        }
+
+        $url = $this->client->makeURL('tag') . $tag;
+        $payload = array('registration_ids'=>$registrationId);
+        return Http::post($this->client, $url, $payload);
+    }
+
+    public function deleteTag($tag) {
+        if (!is_string($tag)) {
+            throw new InvalidArgumentException("Invalid tag");
+        }
+        $url = $this->client->makeURL('tag') . $tag;
+        return Http::delete($this->client, $url);
+    }
+
+    public function getAliasDevices($alias, $platform = null) {
+        if (!is_string($alias)) {
+            throw new InvalidArgumentException("Invalid alias");
+        }
+
+        $url = $this->client->makeURL('alias') . $alias;
+
+        if (!is_null($platform)) {
+            if (is_array($platform)) {
+                $isFirst = true;
+                foreach($platform as $item) {
+                    if ($isFirst) {
+                        $url = $url . '?platform=' . $item;
+                        $isFirst = false;
+                    } else {
+                        $url = $url . ',' . $item;
+                    }
+                }
+            } else if (is_string($platform)) {
+                $url = $url . '?platform=' . $platform;
+            } else {
+                throw new InvalidArgumentException("Invalid platform");
+            }
+        }
+        return Http::get($this->client, $url);
+    }
+
+    public function deleteAlias($alias) {
+        if (!is_string($alias)) {
+            throw new InvalidArgumentException("Invalid alias");
+        }
+        $url = $this->client->makeURL('alias') . $alias;
+        return Http::delete($this->client, $url);
+    }
+
+    public function getDevicesStatus($registrationId) {
+        if (!is_array($registrationId) && !is_string($registrationId)) {
+            throw new InvalidArgumentException('Invalid registration_id');
+        }
+
+        if (is_string($registrationId)) {
+            $registrationId = explode(',', $registrationId);
+        }
+
+        $payload = array();
+        if (count($registrationId) <= 0) {
+            throw new InvalidArgumentException('Invalid registration_id');
+        }
+        $payload['registration_ids'] = $registrationId;
+        $url = $this->client->makeURL('device') . 'status';
+        return Http::post($this->client, $url, $payload);
+    }
+}

+ 9 - 0
vendor/jpush/jpush/src/JPush/Exceptions/APIConnectionException.php

@@ -0,0 +1,9 @@
+<?php
+namespace JPush\Exceptions;
+
+class APIConnectionException extends JPushException {
+
+    function __toString() {
+        return "\n" . __CLASS__ . " -- {$this->message} \n";
+    }
+}

+ 36 - 0
vendor/jpush/jpush/src/JPush/Exceptions/APIRequestException.php

@@ -0,0 +1,36 @@
+<?php
+namespace JPush\Exceptions;
+
+class APIRequestException extends JPushException {
+    private $http_code;
+    private $headers;
+
+    private static $expected_keys = array('code', 'message');
+
+    function __construct($response){
+        $this->http_code = $response['http_code'];
+        $this->headers = $response['headers'];
+
+        $body = json_decode($response['body'], true);
+
+        if (key_exists('error', $body)) {
+            $this->code = $body['error']['code'];
+            $this->message = $body['error']['message'];
+        } else {
+            $this->code = $body['code'];
+            $this->message = $body['message'];
+        }
+    }
+
+    public function __toString() {
+        return "\n" . __CLASS__ . " -- [{$this->code}]: {$this->message} \n";
+    }
+
+    public function getHttpCode() {
+        return $this->http_code;
+    }
+    public function getHeaders() {
+        return $this->headers;
+    }
+
+}

+ 9 - 0
vendor/jpush/jpush/src/JPush/Exceptions/JPushException.php

@@ -0,0 +1,9 @@
+<?php
+namespace JPush\Exceptions;
+
+class JPushException extends \Exception {
+
+    function __construct($message) {
+        parent::__construct($message);
+    }
+}

+ 25 - 0
vendor/jpush/jpush/src/JPush/Exceptions/ServiceNotAvaliable.php

@@ -0,0 +1,25 @@
+<?php
+namespace JPush\Exceptions;
+
+class ServiceNotAvaliable extends JPushException {
+
+    private $http_code;
+    private $headers;
+
+    function __construct($response){
+        $this->http_code = $response['http_code'];
+        $this->headers = $response['headers'];
+        $this->message = $response['body'];
+    }
+
+    function __toString() {
+        return "\n" . __CLASS__ . " -- [{$this->http_code}]: {$this->message} \n";
+    }
+
+    public function getHttpCode() {
+        return $this->http_code;
+    }
+    public function getHeaders() {
+        return $this->headers;
+    }
+}

+ 139 - 0
vendor/jpush/jpush/src/JPush/Http.php

@@ -0,0 +1,139 @@
+<?php
+namespace JPush;
+use JPush\Exceptions\APIConnectionException;
+use JPush\Exceptions\APIRequestException;
+use JPush\Exceptions\ServiceNotAvaliable;
+
+final class Http {
+
+    public static function get($client, $url) {
+        $response = self::sendRequest($client, $url, Config::HTTP_GET, $body=null);
+        return self::processResp($response);
+    }
+    public static function post($client, $url, $body) {
+        $response = self::sendRequest($client, $url, Config::HTTP_POST, $body);
+        return self::processResp($response);
+    }
+    public static function put($client, $url, $body) {
+        $response = self::sendRequest($client, $url, Config::HTTP_PUT, $body);
+        return self::processResp($response);
+    }
+    public static function delete($client, $url) {
+        $response = self::sendRequest($client, $url, Config::HTTP_DELETE, $body=null);
+        return self::processResp($response);
+    }
+
+    private static function sendRequest($client, $url, $method, $body=null, $times=1) {
+        self::log($client, "Send " . $method . " " . $url . ", body:" . json_encode($body) . ", times:" . $times);
+        if (!defined('CURL_HTTP_VERSION_2_0')) {
+            define('CURL_HTTP_VERSION_2_0', 3);
+        }
+        $ch = curl_init();
+        curl_setopt($ch, CURLOPT_URL, $url);
+        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+        curl_setopt($ch, CURLOPT_HEADER, true);
+        curl_setopt($ch, CURLOPT_USERAGENT, Config::USER_AGENT);
+        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, Config::CONNECT_TIMEOUT);  // 连接建立最长耗时
+        curl_setopt($ch, CURLOPT_TIMEOUT, Config::READ_TIMEOUT);  // 请求最长耗时
+        // 设置SSL版本 1=CURL_SSLVERSION_TLSv1, 不指定使用默认值,curl会自动获取需要使用的CURL版本
+        // curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
+        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+        // 如果报证书相关失败,可以考虑取消注释掉该行,强制指定证书版本
+        //curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, 'TLSv1');
+        // 设置Basic认证
+        curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
+        curl_setopt($ch, CURLOPT_USERPWD, $client->getAuthStr());
+        curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
+
+        // 设置Post参数
+        if ($method === Config::HTTP_POST) {
+            curl_setopt($ch, CURLOPT_POST, true);
+        } else if ($method === Config::HTTP_DELETE || $method === Config::HTTP_PUT) {
+            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
+        }
+        if (!is_null($body)) {
+            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
+        }
+
+        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
+            'Content-Type: application/json',
+            'Connection: Keep-Alive'
+        ));
+
+        $output = curl_exec($ch);
+        $response = array();
+        $errorCode = curl_errno($ch);
+
+        // $msg = '';
+        // $data = json_decode($body, true);
+        // if (isset($data['options']['sendno'])) {
+        //     $sendno = $data['options']['sendno'];
+        //     $msg = 'sendno: ' . $sendno;
+        // }
+
+        $msg = '';
+        if (isset($body['options']['sendno'])) {
+            $sendno = $body['options']['sendno'];
+            $msg = 'sendno: ' . $sendno;
+        }
+
+
+        if ($errorCode) {
+            $retries = $client->getRetryTimes();
+            if ($times < $retries) {
+                return self::sendRequest($client, $url, $method, $body, ++$times);
+            } else {
+                if ($errorCode === 28) {
+                    throw new APIConnectionException($msg . "Response timeout. Your request has probably be received by JPush Server,please check that whether need to be pushed again." );
+                } elseif ($errorCode === 56) {
+                // resolve error[56 Problem (2) in the Chunked-Encoded data]
+                    throw new APIConnectionException($msg . "Response timeout, maybe cause by old CURL version. Your request has probably be received by JPush Server, please check that whether need to be pushed again.");
+                } else {
+                    throw new APIConnectionException("$msg . Connect timeout. Please retry later. Error:" . $errorCode . " " . curl_error($ch));
+                }
+            }
+        } else {
+            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+            $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
+            $header_text = substr($output, 0, $header_size);
+            $body = substr($output, $header_size);
+            $headers = array();
+            foreach (explode("\r\n", $header_text) as $i => $line) {
+                if (!empty($line)) {
+                    if ($i === 0) {
+                        $headers[0] = $line;
+                    } else if (strpos($line, ": ")) {
+                        list ($key, $value) = explode(': ', $line);
+                        $headers[$key] = $value;
+                    }
+                }
+            }
+            $response['headers'] = $headers;
+            $response['body'] = $body;
+            $response['http_code'] = $httpCode;
+        }
+        curl_close($ch);
+        return $response;
+    }
+
+    public static function processResp($response) {
+        $data = json_decode($response['body'], true);
+        if ($response['http_code'] === 200) {
+            $result = array();
+            $result['body'] = $data;
+            $result['http_code'] = $response['http_code'];
+            $result['headers'] = $response['headers'];
+            return $result;
+        } elseif (is_null($data)) {
+            throw new ServiceNotAvaliable($response);
+        } else {
+            throw new APIRequestException($response);
+        }
+    }
+
+    public static function log($client, $content) {
+        if (!is_null($client->getLogFile())) {
+            error_log($content . "\r\n", 3, $client->getLogFile());
+        }
+    }
+}

+ 761 - 0
vendor/jpush/jpush/src/JPush/PushPayload.php

@@ -0,0 +1,761 @@
+<?php
+namespace JPush;
+use InvalidArgumentException;
+
+class PushPayload {
+
+    private static $EFFECTIVE_DEVICE_TYPES = array('ios', 'android', 'winphone');
+
+    private $client;
+    private $url;
+
+    private $cid;
+    private $platform;
+
+    private $audience;
+    private $tags;
+    private $tagAnds;
+    private $tagNots;
+    private $alias;
+    private $registrationIds;
+    private $segmentIds;
+    private $abtests;
+
+    private $notificationAlert;
+    private $iosNotification;
+    private $androidNotification;
+    private $winPhoneNotification;
+    private $voip;
+    private $smsMessage;
+    private $message;
+    private $options;
+    private $custom;
+
+    /**
+     * PushPayload constructor.
+     * @param $client JPush
+     */
+    function __construct($client) {
+        $this->client = $client;
+        $url = $this->client->is_group() ? 'grouppush' : 'push';
+        $this->url = $this->client->makeURL('push') . $url;
+    }
+
+    public function getCid($count = 1, $type = 'push') {
+        $url = $this->client->makeURL('push') . 'push/cid?count=' . $count . '&type=' . $type;
+        return Http::get($this->client, $url);
+    }
+
+    public function setCid($cid) {
+        $this->cid = trim($cid);
+        return $this;
+    }
+
+    public function setPlatform($platform) {
+        # $required_keys = array('all', 'android', 'ios', 'winphone');
+        if (is_string($platform)) {
+            $ptf = strtolower($platform);
+            if ('all' === $ptf) {
+                $this->platform = 'all';
+            } elseif (in_array($ptf, self::$EFFECTIVE_DEVICE_TYPES)) {
+                $this->platform = array($ptf);
+            }
+        } elseif (is_array($platform)) {
+            $ptf = array_map('strtolower', $platform);
+            $this->platform = array_intersect($ptf, self::$EFFECTIVE_DEVICE_TYPES);
+        }
+        return $this;
+    }
+
+    public function setAudience($all) {
+        if (strtolower($all) === 'all') {
+            $this->addAllAudience();
+            return $this;
+        } else {
+            throw new InvalidArgumentException('Invalid audience value');
+        }
+    }
+
+    public function addAllAudience() {
+        $this->audience = "all";
+        return $this;
+    }
+
+    public function addTag($tag) {
+        return $this->updateAudience('tags', $tag, 'tag');
+    }
+
+    public function addTagAnd($tag) {
+        return $this->updateAudience('tagAnds', $tag, 'tag_and');
+    }
+
+    public function addTagNot($tag) {
+        return $this->updateAudience('tagNots', $tag, 'tag_not');
+    }
+
+    public function addAlias($alias) {
+        return $this->updateAudience('alias', $alias, 'alias');
+    }
+
+    public function addRegistrationId($registrationId) {
+        return $this->updateAudience('registrationIds', $registrationId, 'registration_id');
+    }
+
+    public function addSegmentId($segmentId) {
+        return $this->updateAudience('segmentIds', $segmentId, 'segment');
+    }
+
+    public function addAbtest($abtest) {
+        return $this->updateAudience('abtests', $abtest, 'abtest');
+    }
+
+    private function updateAudience($key, $value, $name) {
+        if (is_null($this->$key)) {
+            $this->$key = array();
+        }
+
+        if (is_array($value)) {
+            foreach($value as $v) {
+                if (!is_string($v)) {
+                    throw new InvalidArgumentException("Invalid $name value");
+                }
+                if (!in_array($v, $this->$key)) {
+                    array_push($this->$key, $v);
+                }
+            }
+        } else if (is_string($value)) {
+            if (!in_array($value, $this->$key)) {
+                array_push($this->$key, $value);
+            }
+        } else {
+            throw new InvalidArgumentException("Invalid $name value");
+        }
+
+        return $this;
+    }
+
+    public function setNotificationAlert($alert) {
+        if (!is_string($alert)) {
+            throw new InvalidArgumentException("Invalid alert value");
+        }
+        $this->notificationAlert = $alert;
+        return $this;
+    }
+
+    public function addWinPhoneNotification($alert=null, $title=null, $_open_page=null, $extras=null) {
+        $winPhone = array();
+
+        if (!is_null($alert)) {
+            if (!is_string($alert)) {
+                throw new InvalidArgumentException("Invalid winphone notification");
+            }
+            $winPhone['alert'] = $alert;
+        }
+
+        if (!is_null($title)) {
+            if (!is_string($title)) {
+                throw new InvalidArgumentException("Invalid winphone title notification");
+            }
+            if(strlen($title) > 0) {
+                $winPhone['title'] = $title;
+            }
+        }
+
+        if (!is_null($_open_page)) {
+            if (!is_string($_open_page)) {
+                throw new InvalidArgumentException("Invalid winphone _open_page notification");
+            }
+            if (strlen($_open_page) > 0) {
+                $winPhone['_open_page'] = $_open_page;
+            }
+        }
+
+        if (!is_null($extras)) {
+            if (!is_array($extras)) {
+                throw new InvalidArgumentException("Invalid winphone extras notification");
+            }
+            if (count($extras) > 0) {
+                $winPhone['extras'] = $extras;
+            }
+        }
+
+        if (count($winPhone) <= 0) {
+            throw new InvalidArgumentException("Invalid winphone notification");
+        }
+
+        $this->winPhoneNotification = $winPhone;
+        return $this;
+    }
+
+    public function setSms($delay_time, $temp_id, array $temp_para = []) {
+        $sms = array();
+        $sms['temp_id'] = $temp_id;
+        $sms['delay_time'] = ($delay_time === 0 || (is_int($delay_time) && $delay_time > 0 && $delay_time <= 86400)) ? $delay_time : 0;
+
+        if (!empty($temp_para)) {
+            $sms['temp_para'] = $temp_para;
+        }
+
+        $this->smsMessage = $sms;
+        return $this;
+    }
+
+    public function build() {
+        $payload = array();
+
+        // validate platform
+        if (is_null($this->platform)) {
+            throw new InvalidArgumentException("platform must be set");
+        }
+        $payload["platform"] = $this->platform;
+
+        if (!is_null($this->cid)) {
+            $payload['cid'] = $this->cid;
+        }
+
+        // validate audience
+        $audience = array();
+        if (!is_null($this->tags)) {
+            $audience["tag"] = $this->tags;
+        }
+        if (!is_null($this->tagAnds)) {
+            $audience["tag_and"] = $this->tagAnds;
+        }
+        if (!is_null($this->tagNots)) {
+            $audience["tag_not"] = $this->tagNots;
+        }
+        if (!is_null($this->alias)) {
+            $audience["alias"] = $this->alias;
+        }
+        if (!is_null($this->registrationIds)) {
+            $audience["registration_id"] = $this->registrationIds;
+        }
+        if (!is_null($this->segmentIds)) {
+            $audience["segment"] = $this->segmentIds;
+        }
+        if (!is_null($this->abtests)) {
+            $audience["abtest"] = $this->abtests;
+        }
+        if (is_null($this->audience) && count($audience) <= 0) {
+            throw new InvalidArgumentException("audience must be set");
+        } else if (!is_null($this->audience) && count($audience) > 0) {
+            throw new InvalidArgumentException("you can't add tags/alias/registration_id/tag_and when audience='all'");
+        } else if (is_null($this->audience)) {
+            $payload["audience"] = $audience;
+        } else {
+            $payload["audience"] = $this->audience;
+        }
+
+
+        // validate notification
+        $notification = array();
+
+        if (!is_null($this->notificationAlert)) {
+            $notification['alert'] = $this->notificationAlert;
+        }
+
+        if (!is_null($this->androidNotification)) {
+            $notification['android'] = $this->androidNotification;
+            if (is_null($this->androidNotification['alert'])) {
+                if (is_null($this->notificationAlert)) {
+                    throw new InvalidArgumentException("Android alert can not be null");
+                } else {
+                    $notification['android']['alert'] = $this->notificationAlert;
+                }
+            }
+        }
+
+        if (!is_null($this->iosNotification)) {
+            $notification['ios'] = $this->iosNotification;
+            if (is_null($this->iosNotification['alert'])) {
+                if (is_null($this->notificationAlert)) {
+                    throw new InvalidArgumentException("iOS alert can not be null");
+                } else {
+                    $notification['ios']['alert'] = $this->notificationAlert;
+                }
+            }
+        }
+
+        if (!is_null($this->winPhoneNotification)) {
+            $notification['winphone'] = $this->winPhoneNotification;
+            if (is_null($this->winPhoneNotification['alert'])) {
+                if (is_null($this->winPhoneNotification)) {
+                    throw new InvalidArgumentException("WinPhone alert can not be null");
+                } else {
+                    $notification['winphone']['alert'] = $this->notificationAlert;
+                }
+            }
+        }
+
+        if (!is_null($this->voip)) {
+            $notification['voip'] = $this->voip;
+        }
+
+        if (count($notification) > 0) {
+            $payload['notification'] = $notification;
+        }
+
+        if (!is_null($this->message)) {
+            $payload['message'] = $this->message;
+        }
+        if (!array_key_exists('notification', $payload) && !array_key_exists('message', $payload)) {
+            throw new InvalidArgumentException('notification and message can not all be null');
+        }
+
+        if (!is_null($this->smsMessage)) {
+            $payload['sms_message'] = $this->smsMessage;
+        }
+
+        if (is_null($this->options)) {
+            $this->options();
+        }
+
+        $payload['options'] = $this->options;
+
+        if (!is_null($this->custom)) {
+            foreach($this->custom as $key=>$val) {
+                $payload[$key] = $val;
+            }
+        }
+
+        return $payload;
+    }
+
+    public function toJSON() {
+        $payload = $this->build();
+        return json_encode($payload);
+    }
+
+    public function printJSON() {
+        echo $this->toJSON();
+        return $this;
+    }
+
+    public function send() {
+        return Http::post($this->client, $this->url, $this->build());
+    }
+
+    public function validate() {
+        $url = $this->client->makeURL('push') . '/push/validate';
+        return Http::post($this->client, $url, $this->build());
+    }
+
+    private function generateSendno() {
+        return rand(100000, getrandmax());
+    }
+
+    # new methods
+    public function iosNotification($alert = '', array $notification = array()) {
+        $ios = array();
+        $ios['alert'] = (is_string($alert) || is_array($alert)) ? $alert : '';
+        if (!empty($notification)) {
+            if (isset($notification['sound'])) {
+                if (is_string($notification['sound']) || is_array($notification['sound'])) {
+                    $ios['sound'] = $notification['sound'];
+                } else {
+                    unset($notification['sound']);
+                }
+            }
+            if (isset($notification['content-available'])) {
+                if (is_bool($notification['content-available'])) {
+                    $ios['content-available'] = $notification['content-available'];
+                } else {
+                    unset($notification['content-available']);
+                }
+            }
+            if (isset($notification['mutable-content'])) {
+                if (is_bool($notification['mutable-content'])) {
+                    $ios['mutable-content'] = $notification['mutable-content'];
+                } else {
+                    unset($notification['mutable-content']);
+                }
+            }
+            if (isset($notification['extras'])) {
+                if (is_array($notification['extras']) && !empty($notification['extras'])) {
+                    $ios['extras'] = $notification['extras'];
+                } else {
+                    unset($notification['extras']);
+                }
+            }
+            $ios = array_merge($notification, $ios);
+        }
+        if (!isset($ios['sound'])) {
+            $ios['sound'] = '';
+        }
+        if (!isset($ios['badge'])) {
+            $ios['badge'] = '+1';
+        }
+        $this->iosNotification = $ios;
+        return $this;
+    }
+
+    public function androidNotification($alert = '', array $notification = array()) {
+        $android = array();
+        $android['alert'] = is_string($alert) ? $alert : '';
+        if (!empty($notification)) {
+            if (isset($notification['builder_id'])) {
+                if (is_int($notification['builder_id'])) {
+                    $android['builder_id'] = $notification['builder_id'];
+                } else {
+                    unset($notification['builder_id']);
+                }
+            }
+            if (isset($notification['priority'])) {
+                if (is_int($notification['priority'])) {
+                    $android['priority'] = $notification['priority'];
+                } else {
+                    unset($notification['priority']);
+                }
+            }
+            if (isset($notification['style'])) {
+                if (is_int($notification['style'])) {
+                    $android['style'] = $notification['style'];
+                } else {
+                    unset($notification['style']);
+                }
+            }
+            if (isset($notification['alert_type'])) {
+                if (is_int($notification['alert_type'])) {
+                    $android['alert_type'] = $notification['alert_type'];
+                } else {
+                    unset($notification['alert_type']);
+                }
+            }
+            if (isset($notification['inbox'])) {
+                if (is_array($notification['inbox']) && !empty($notification['inbox'])) {
+                    $android['inbox'] = $notification['inbox'];
+                } else {
+                    unset($notification['inbox']);
+                }
+            }
+            if (isset($notification['intent'])) {
+                if (is_array($notification['intent']) && !empty($notification['intent'])) {
+                    $android['intent'] = $notification['intent'];
+                } else {
+                    unset($notification['intent']);
+                }
+            }
+            if (isset($notification['extras'])) {
+                if (is_array($notification['extras']) && !empty($notification['extras'])) {
+                    $android['extras'] = $notification['extras'];
+                } else {
+                    unset($notification['extras']);
+                }
+            }
+            $android = array_merge($notification, $android);
+        }
+        $this->androidNotification = $android;
+        return $this;
+    }
+
+    /**
+     * Voip in notification
+     * could add any custom key/value into it
+     */
+    public function voip (array $extras = array()) {
+        $voip = array();
+        if(!empty($extras)) {
+            foreach($extras as $key=>$val) {
+                $voip[$key] = $val;
+            }
+        }
+        $voip = array_merge($extras, $voip);
+        $this->voip=$voip;        
+        return $this;
+    }
+
+    public function message($msg_content, array $msg = array()) {
+        # $required_keys = array('title', 'content_type', 'extras');
+        if (is_string($msg_content)) {
+            $message = array();
+            $message['msg_content'] = $msg_content;
+            if (!empty($msg)) {
+                if (isset($msg['title']) && is_string($msg['title'])) {
+                    $message['title'] = $msg['title'];
+                }
+                if (isset($msg['content_type']) && is_string($msg['content_type'])) {
+                    $message['content_type'] = $msg['content_type'];
+                }
+                if (isset($msg['extras']) && is_array($msg['extras']) && !empty($msg['extras'])) {
+                    $message['extras'] = $msg['extras'];
+                }
+            }
+            $this->message = $message;
+        }
+        return $this;
+    }
+
+    public function options(array $opts = array()) {
+        # $required_keys = array('sendno', 'time_to_live', 'override_msg_id', 'apns_production', 'apns_collapse_id', 'big_push_duration');
+        $options = array();
+        if (isset($opts['sendno'])) {
+            $options['sendno'] = $opts['sendno'];
+        } else {
+            $options['sendno'] = $this->generateSendno();
+        }
+        if (isset($opts['time_to_live']) && $opts['time_to_live'] <= 864000 && $opts['time_to_live'] >= 0) {
+            $options['time_to_live'] = $opts['time_to_live'];
+        }
+        if (isset($opts['override_msg_id'])) {
+            $options['override_msg_id'] = $opts['override_msg_id'];
+        }
+        if (isset($opts['apns_production'])) {
+            $options['apns_production'] = (bool)$opts['apns_production'];
+        } else {
+            $options['apns_production'] = false;
+        }
+        if (isset($opts['apns_collapse_id'])) {
+            $options['apns_collapse_id'] = $opts['apns_collapse_id'];
+        }
+        if (isset($opts['big_push_duration']) && $opts['big_push_duration'] <= 1400 && $opts['big_push_duration'] >= 0) {
+            $options['big_push_duration'] = $opts['big_push_duration'];
+        }
+        $options = array_merge($opts, $options);
+        $this->options = $options;
+
+        return $this;
+    }
+
+    public function custom (array $extras = array()) {
+        if(!empty($extras)) {
+            $this->custom=$extras;        
+        }
+        return $this;
+    }
+
+    ###############################################################################
+    ############# 以下函数已过期,不推荐使用,仅作为兼容接口存在 #########################
+    ###############################################################################
+    public function addIosNotification($alert=null, $sound=null, $badge=null, $content_available=null, $category=null, $extras=null) {
+        $ios = array();
+
+        if (!is_null($alert)) {
+            if (!is_string($alert) && !is_array($alert)) {
+                throw new InvalidArgumentException("Invalid ios alert value");
+            }
+            $ios['alert'] = $alert;
+        }
+
+        if (!is_null($sound)) {
+            if (!is_string($sound)) {
+                throw new InvalidArgumentException("Invalid ios sound value");
+            }
+            if ($sound !== Config::DISABLE_SOUND) {
+                $ios['sound'] = $sound;
+            }
+        } else {
+            // 默认sound为''
+            $ios['sound'] = '';
+        }
+
+        if (!is_null($badge)) {
+            if (is_string($badge) && !preg_match("/^[+-]{1}[0-9]{1,3}$/", $badge)) {
+                if (!is_int($badge)) {
+                    throw new InvalidArgumentException("Invalid ios badge value");
+                }
+            }
+            if ($badge != Config::DISABLE_BADGE) {
+                $ios['badge'] = $badge;
+            }
+        } else {
+            // 默认badge为'+1'
+            $ios['badge'] = '+1';
+        }
+
+        if (!is_null($content_available)) {
+            if (!is_bool($content_available)) {
+                throw new InvalidArgumentException("Invalid ios content-available value");
+            }
+            $ios['content-available'] = $content_available;
+        }
+
+        if (!is_null($category)) {
+            if (!is_string($category)) {
+                throw new InvalidArgumentException("Invalid ios category value");
+            }
+            if (strlen($category)) {
+                $ios['category'] = $category;
+            }
+        }
+
+        if (!is_null($extras)) {
+            if (!is_array($extras)) {
+                throw new InvalidArgumentException("Invalid ios extras value");
+            }
+            if (count($extras) > 0) {
+                $ios['extras'] = $extras;
+            }
+        }
+
+        if (count($ios) <= 0) {
+            throw new InvalidArgumentException("Invalid iOS notification");
+        }
+
+        $this->iosNotification = $ios;
+        return $this;
+    }
+
+    public function addAndroidNotification($alert=null, $title=null, $builderId=null, $extras=null) {
+        $android = array();
+
+        if (!is_null($alert)) {
+            if (!is_string($alert)) {
+                throw new InvalidArgumentException("Invalid android alert value");
+            }
+            $android['alert'] = $alert;
+        }
+
+        if (!is_null($title)) {
+            if(!is_string($title)) {
+                throw new InvalidArgumentException("Invalid android title value");
+            }
+            if(strlen($title) > 0) {
+                $android['title'] = $title;
+            }
+        }
+
+        if (!is_null($builderId)) {
+            if (!is_int($builderId)) {
+                throw new InvalidArgumentException("Invalid android builder_id value");
+            }
+            $android['builder_id'] = $builderId;
+        }
+
+        if (!is_null($extras)) {
+            if (!is_array($extras)) {
+                throw new InvalidArgumentException("Invalid android extras value");
+            }
+            if (count($extras) > 0) {
+                $android['extras'] = $extras;
+            }
+        }
+
+        if (count($android) <= 0) {
+            throw new InvalidArgumentException("Invalid android notification");
+        }
+
+        $this->androidNotification = $android;
+        return $this;
+    }
+
+    public function setMessage($msg_content, $title=null, $content_type=null, $extras=null) {
+        $message = array();
+
+        if (is_null($msg_content) || !is_string($msg_content)) {
+            throw new InvalidArgumentException("Invalid message content");
+        } else {
+            $message['msg_content'] = $msg_content;
+        }
+
+        if (!is_null($title)) {
+            if (!is_string($title)) {
+                throw new InvalidArgumentException("Invalid message title");
+            }
+            $message['title'] = $title;
+        }
+
+        if (!is_null($content_type)) {
+            if (!is_string($content_type)) {
+                throw new InvalidArgumentException("Invalid message content type");
+            }
+            $message["content_type"] = $content_type;
+        }
+
+        if (!is_null($extras)) {
+            if (!is_array($extras)) {
+                throw new InvalidArgumentException("Invalid message extras");
+            }
+            if (count($extras) > 0) {
+                $message['extras'] = $extras;
+            }
+        }
+
+        $this->message = $message;
+        return $this;
+    }
+
+    public function setSmsMessage($smsMessage) {
+        $this->smsMessage = $smsMessage;
+        return $this;
+    }
+
+    public function setOptions($sendno=null, $time_to_live=null, $override_msg_id=null, $apns_production=null, $big_push_duration=null) {
+        $options = array();
+
+        if (!is_null($sendno)) {
+            if (!is_int($sendno)) {
+                throw new InvalidArgumentException('Invalid option sendno');
+            }
+            $options['sendno'] = $sendno;
+        } else {
+            $options['sendno'] = $this->generateSendno();
+        }
+
+        if (!is_null($time_to_live)) {
+            if (!is_int($time_to_live) || $time_to_live < 0 || $time_to_live > 864000) {
+                throw new InvalidArgumentException('Invalid option time to live, it must be a int and in [0, 864000]');
+            }
+            $options['time_to_live'] = $time_to_live;
+        }
+
+        if (!is_null($override_msg_id)) {
+            if (!is_long($override_msg_id)) {
+                throw new InvalidArgumentException('Invalid option override msg id');
+            }
+            $options['override_msg_id'] = $override_msg_id;
+        }
+
+        if (!is_null($apns_production)) {
+            if (!is_bool($apns_production)) {
+                throw new InvalidArgumentException('Invalid option apns production');
+            }
+            $options['apns_production'] = $apns_production;
+        } else {
+            $options['apns_production'] = false;
+        }
+
+        if (!is_null($big_push_duration)) {
+            if (!is_int($big_push_duration) || $big_push_duration < 0 || $big_push_duration > 1440) {
+                throw new InvalidArgumentException('Invalid option big push duration, it must be a int and in [0, 1440]');
+            }
+            $options['big_push_duration'] = $big_push_duration;
+        }
+
+        $this->options = $options;
+        return $this;
+    }
+
+    /*
+     针对RegID方式批量单推
+     https://docs.jiguang.cn/jpush/server/push/rest_api_v3_push/#vip
+    */
+    public function batchPushByRegid(array $singlePayloads) {
+        $body = array(
+            "pushlist"=>array()
+        );
+        $response = $this -> getCid(count($singlePayloads), 'push');
+        $cidlist = $response['body']['cidlist'];
+        foreach ($cidlist as $i => $cid) {
+            $body["pushlist"][$cid] = $singlePayloads[$i];
+        }
+        $url = $this->client->makeURL('push') . 'push/batch/regid/single';
+        return Http::post($this->client, $url, $body);
+    }
+
+    /*
+     针对Alias方式批量单推
+     https://docs.jiguang.cn/jpush/server/push/rest_api_v3_push/#vip
+    */
+    public function batchPushByAlias(array $singlePayloads) {
+        $body = array(
+            "pushlist"=>array()
+        );
+        $response = $this -> getCid(count($singlePayloads), 'push');
+        $cidlist = $response['body']['cidlist'];
+        foreach ($cidlist as $i => $cid) {
+            $body["pushlist"][$cid] = $singlePayloads[$i];
+        }
+        $url = $this->client->makeURL('push') . 'push/batch/alias/single';
+        return Http::post($this->client, $url, $body);
+    }
+}

+ 109 - 0
vendor/jpush/jpush/src/JPush/ReportPayload.php

@@ -0,0 +1,109 @@
+<?php
+namespace JPush;
+use InvalidArgumentException;
+
+class ReportPayload {
+    private static $EFFECTIVE_TIME_UNIT = array('HOUR', 'DAY', 'MONTH');
+
+    private $client;
+
+    /**
+     * ReportPayload constructor.
+     * @param $client JPush
+     */
+    public function __construct($client)
+    {
+        $this->client = $client;
+    }
+
+    public function getReceived($msgIds) {
+        $queryParams = '?msg_ids=';
+        if (is_array($msgIds) && !empty($msgIds)) {
+            $msgIdsStr = implode(',', $msgIds);
+            $queryParams .= $msgIdsStr;
+        } elseif (is_string($msgIds)) {
+            $queryParams .= $msgIds;
+        } else {
+            throw new InvalidArgumentException("Invalid msg_ids");
+        }
+
+        $url = $this->client->makeURL('report') . 'received' . $queryParams;
+        return Http::get($this->client, $url);
+    }
+
+    /*
+     送达统计详情(新)
+     https://docs.jiguang.cn/jpush/server/push/rest_api_v3_report/#_7
+    */
+    public function getReceivedDetail($msgIds) {
+        $queryParams = '?msg_ids=';
+        if (is_array($msgIds) && !empty($msgIds)) {
+            $msgIdsStr = implode(',', $msgIds);
+            $queryParams .= $msgIdsStr;
+        } elseif (is_string($msgIds)) {
+            $queryParams .= $msgIds;
+        } else {
+            throw new InvalidArgumentException("Invalid msg_ids");
+        }
+
+        $url = $this->client->makeURL('report') . 'received/detail' . $queryParams;
+        return Http::get($this->client, $url);
+    }
+
+    public function getMessageStatus($msgId, $rids, $data = null) {
+        $url = $this->client->makeURL('report') . 'status/message';
+        $registrationIds = is_array($rids) ? $rids : array($rids);
+        $body = [
+            'msg_id' => $msgId,
+            'registration_ids' => $registrationIds
+        ];
+        if (!is_null($data)) {
+            $body['data'] = $data;
+        }
+        return Http::post($this->client, $url, $body);
+    }
+
+    public function getMessages($msgIds) {
+        $queryParams = '?msg_ids=';
+        if (is_array($msgIds) && !empty($msgIds)) {
+            $msgIdsStr = implode(',', $msgIds);
+            $queryParams .= $msgIdsStr;
+        } elseif (is_string($msgIds)) {
+            $queryParams .= $msgIds;
+        } else {
+            throw new InvalidArgumentException("Invalid msg_ids");
+        }
+
+        $url = $this->client->makeURL('report') . 'messages/' .$queryParams;
+        return Http::get($this->client, $url);
+    }
+
+    /*
+     消息统计详情(VIP 专属接口,新)
+     https://docs.jiguang.cn/jpush/server/push/rest_api_v3_report/#vip_1
+    */
+    public function getMessagesDetail($msgIds) {
+        $queryParams = '?msg_ids=';
+        if (is_array($msgIds) && !empty($msgIds)) {
+            $msgIdsStr = implode(',', $msgIds);
+            $queryParams .= $msgIdsStr;
+        } elseif (is_string($msgIds)) {
+            $queryParams .= $msgIds;
+        } else {
+            throw new InvalidArgumentException("Invalid msg_ids");
+        }
+
+        $url = $this->client->makeURL('report') . 'messages/detail' .$queryParams;
+        return Http::get($this->client, $url);
+    }
+
+    public function getUsers($time_unit, $start, $duration) {
+        $time_unit = strtoupper($time_unit);
+        if (!in_array($time_unit, self::$EFFECTIVE_TIME_UNIT)) {
+            throw new InvalidArgumentException('Invalid time unit');
+        }
+
+        $url = $this->client->makeURL('report') . 'users/?time_unit=' . $time_unit . '&start=' . $start . '&duration=' . $duration;
+        return Http::get($this->client, $url);
+    }
+}

+ 182 - 0
vendor/jpush/jpush/src/JPush/SchedulePayload.php

@@ -0,0 +1,182 @@
+<?php
+namespace JPush;
+use InvalidArgumentException;
+
+class SchedulePayload {
+
+    private $client;
+
+    /**
+     * SchedulePayload constructor.
+     * @param $client JPush
+     */
+    public function __construct($client) {
+        $this->client = $client;
+    }
+
+    public function createSingleSchedule($name, $push_payload, $trigger) {
+        if (!is_string($name)) {
+            throw new InvalidArgumentException('Invalid schedule name');
+        }
+        if (!is_array($push_payload)) {
+            throw new InvalidArgumentException('Invalid schedule push payload');
+        }
+        if (!is_array($trigger)) {
+            throw new InvalidArgumentException('Invalid schedule trigger');
+        }
+        $payload = array();
+        $payload['name'] = $name;
+        $payload['enabled'] = true;
+        $payload['trigger'] = array("single"=>$trigger);
+        $payload['push'] = $push_payload;
+
+        $url = $this->client->makeURL('schedule');
+        return Http::post($this->client, $url, $payload);
+    }
+
+    public function createPeriodicalSchedule($name, $push_payload, $trigger) {
+        if (!is_string($name)) {
+            throw new InvalidArgumentException('Invalid schedule name');
+        }
+        if (!is_array($push_payload)) {
+            throw new InvalidArgumentException('Invalid schedule push payload');
+        }
+        if (!is_array($trigger)) {
+            throw new InvalidArgumentException('Invalid schedule trigger');
+        }
+        $payload = array();
+        $payload['name'] = $name;
+        $payload['enabled'] = true;
+        $payload['trigger'] = array("periodical"=>$trigger);
+        $payload['push'] = $push_payload;
+
+        $url = $this->client->makeURL('schedule');
+        return Http::post($this->client, $url, $payload);
+    }
+
+    public function updateSingleSchedule($schedule_id, $name=null, $enabled=null, $push_payload=null, $trigger=null) {
+        if (!is_string($schedule_id)) {
+            throw new InvalidArgumentException('Invalid schedule id');
+        }
+        $payload = array();
+        if (!is_null($name)) {
+            if (!is_string($name)) {
+                throw new InvalidArgumentException('Invalid schedule name');
+            } else {
+                $payload['name'] = $name;
+            }
+        }
+
+        if (!is_null($enabled)) {
+            if (!is_bool($enabled)) {
+                throw new InvalidArgumentException('Invalid schedule enable');
+            } else {
+                $payload['enabled'] = $enabled;
+            }
+        }
+
+        if (!is_null($push_payload)) {
+            if (!is_array($push_payload)) {
+                throw new InvalidArgumentException('Invalid schedule push payload');
+            } else {
+                $payload['push'] = $push_payload;
+            }
+        }
+
+        if (!is_null($trigger)) {
+            if (!is_array($trigger)) {
+                throw new InvalidArgumentException('Invalid schedule trigger');
+            } else {
+                $payload['trigger'] = array("single"=>$trigger);
+            }
+        }
+
+        if (count($payload) <= 0) {
+            throw new InvalidArgumentException('Invalid schedule, name, enabled, trigger, push can not all be null');
+        }
+
+        $url = $this->client->makeURL('schedule') . "/" . $schedule_id;
+
+        return Http::put($this->client, $url, $payload);
+
+    }
+
+    public function updatePeriodicalSchedule($schedule_id, $name=null, $enabled=null, $push_payload=null, $trigger=null) {
+        if (!is_string($schedule_id)) {
+            throw new InvalidArgumentException('Invalid schedule id');
+        }
+        $payload = array();
+        if (!is_null($name)) {
+            if (!is_string($name)) {
+                throw new InvalidArgumentException('Invalid schedule name');
+            } else {
+                $payload['name'] = $name;
+            }
+        }
+
+        if (!is_null($enabled)) {
+            if (!is_bool($enabled)) {
+                throw new InvalidArgumentException('Invalid schedule enable');
+            } else {
+                $payload['enabled'] = $enabled;
+            }
+        }
+
+        if (!is_null($push_payload)) {
+            if (!is_array($push_payload)) {
+                throw new InvalidArgumentException('Invalid schedule push payload');
+            } else {
+                $payload['push'] = $push_payload;
+            }
+        }
+
+        if (!is_null($trigger)) {
+            if (!is_array($trigger)) {
+                throw new InvalidArgumentException('Invalid schedule trigger');
+            } else {
+                $payload['trigger'] = array("periodical"=>$trigger);
+            }
+        }
+
+        if (count($payload) <= 0) {
+            throw new InvalidArgumentException('Invalid schedule, name, enabled, trigger, push can not all be null');
+        }
+
+        $url = $this->client->makeURL('schedule') . "/" . $schedule_id;
+        return Http::put($this->client, $url, $payload);
+    }
+
+    public function getSchedules($page = 1) {
+        if (!is_int($page)) {
+            $page = 1;
+        }
+        $url = $this->client->makeURL('schedule') . "?page=" . $page;
+        return Http::get($this->client, $url);
+    }
+
+    public function getSchedule($schedule_id) {
+        if (!is_string($schedule_id)) {
+            throw new InvalidArgumentException('Invalid schedule id');
+        }
+        $url = $this->client->makeURL('schedule') . "/" . $schedule_id;
+        return Http::get($this->client, $url);
+    }
+
+    public function deleteSchedule($schedule_id) {
+        if (!is_string($schedule_id)) {
+            throw new InvalidArgumentException('Invalid schedule id');
+        }
+        $url = $this->client->makeURL('schedule') . "/" . $schedule_id;
+        return Http::delete($this->client, $url);
+    }
+
+    public function getMsgIds($schedule_id) {
+        if (!is_string($schedule_id)) {
+            throw new InvalidArgumentException('Invalid schedule id');
+        }
+        $url = $this->client->makeURL('schedule') . '/' . $schedule_id . '/msg_ids';
+        return Http::get($this->client, $url);
+    }
+
+}
+

+ 4 - 0
vendor/jpush/jpush/src/JPush/version.php

@@ -0,0 +1,4 @@
+<?php
+namespace JPush;
+
+  const VERSION = '3.6.5';

+ 131 - 0
vendor/jpush/jpush/tests/JPush/DevicePayloadTest.php

@@ -0,0 +1,131 @@
+<?php
+namespace JPush\Tests;
+use PHPUnit\Framework\TestCase;
+
+class DevicePayloadTest extends TestCase {
+
+    protected function setUp() {
+        global $client;
+        $this->device = $client->device();
+        $this->test_tag = 'jpush_tag';
+    }
+
+    function testGetDevices() {
+        global $registration_id;
+        $response = $this->device->getDevices($registration_id);
+        $this->assertEquals('200', $response['http_code']);
+
+        echo "HTTP HEADERS ARE: ";
+        print_r($response['headers']);
+
+        $body = $response['body'];
+        $this->assertTrue(is_array($body));
+        $this->assertEquals(3, count($body));
+        $this->assertArrayHasKey('tags', $body);
+        $this->assertArrayHasKey('alias', $body);
+        $this->assertArrayHasKey('mobile', $body);
+        $this->assertTrue(is_array($body['tags']));
+    }
+
+    /**
+     * @expectedException \JPush\Exceptions\APIRequestException
+     * @expectedExceptionCode 7002
+     */
+    function testGetDevicesWithInvalidRid() {
+        $response = $this->device->getDevices('INVALID_REGISTRATION_ID');
+    }
+
+    function testUpdateDevicesAlias() {
+        global $registration_id;
+        $result = $this->device->getDevices($registration_id);
+        $old_alias = $result['body']['alias'];
+        if ($old_alias == null) {
+            $old_alias = '';
+        }
+        $new_alias = 'jpush_alias';
+        if ($old_alias == $new_alias) {
+            $new_alias = $new_alias . time();
+        }
+        $response = $this->device->updateAlias($registration_id, $new_alias);
+        $this->assertEquals('200', $response['http_code']);
+
+        $response = $this->device->updateAlias($registration_id, $old_alias);
+        $this->assertEquals('200', $response['http_code']);
+    }
+
+    function testUpdateDevicesTags() {
+        global $registration_id;
+        $new_tag = $this->test_tag;
+
+        $response = $this->device->addTags($registration_id, array($new_tag));
+        $this->assertEquals('200', $response['http_code']);
+
+        $response = $this->device->removeTags($registration_id, array($new_tag));
+        $this->assertEquals('200', $response['http_code']);
+    }
+
+    function testGetTags() {
+        $response = $this->device->getTags();
+        $this->assertEquals('200', $response['http_code']);
+
+        $body = $response['body'];
+        $this->assertTrue(is_array($body));
+        $this->assertEquals(1, count($body));
+        $this->assertArrayHasKey('tags', $body);
+    }
+
+    function testIsDeviceInTag() {
+        global $registration_id;
+        $test_tag = $this->test_tag;
+
+        $this->device->addTags($registration_id, array($test_tag));
+        $response = $this->device->isDeviceInTag($registration_id, $test_tag);
+        $this->assertEquals('200', $response['http_code']);
+        $body = $response['body'];
+        $this->assertTrue(is_array($body));
+        $this->assertTrue($body['result']);
+
+        $this->device->removeTags($registration_id, array($test_tag));
+        $response = $this->device->isDeviceInTag($registration_id, $test_tag);
+        $this->assertEquals('200', $response['http_code']);
+        $body = $response['body'];
+        $this->assertTrue(is_array($body));
+        $this->assertFalse($body['result']);
+    }
+
+    function testUpdateTag() {
+        global $registration_id;
+        $test_tag = $this->test_tag;
+
+        $response = $this->device->addDevicesToTag($test_tag, array($registration_id));
+        $this->assertEquals('200', $response['http_code']);
+
+        $response = $this->device->removeDevicesFromTag($test_tag, array($registration_id));
+        $this->assertEquals('200', $response['http_code']);
+    }
+
+    function testDeleteTag() {}
+
+    function testGetAliasDevices() {
+        $test_tag = $this->test_tag;
+
+        $response = $this->device->getAliasDevices($test_tag);
+        $this->assertEquals('200', $response['http_code']);
+        $body = $response['body'];
+        $this->assertTrue(is_array($body));
+        $this->assertEquals(1, count($body));
+        $this->assertArrayHasKey('registration_ids', $body);
+    }
+
+    function testDeleteAlias() {}
+
+    function testGetDevicesStatus() {
+        global $registration_id;
+        $response = $this->device->getDevicesStatus($registration_id);
+        $this->assertEquals('200', $response['http_code']);
+        $body = $response['body'];
+        $this->assertTrue(is_array($body));
+        $this->assertEquals(1, count($body));
+    }
+
+}

+ 315 - 0
vendor/jpush/jpush/tests/JPush/PushPayloadTest.php

@@ -0,0 +1,315 @@
+<?php
+namespace JPush\Tests;
+use PHPUnit\Framework\TestCase;
+
+class PushPayloadTest extends TestCase {
+
+    protected function setUp() {
+        global $client;
+        $this->payload = $client->push()
+                                ->setPlatform('all')
+                                ->addAllAudience()
+                                ->setNotificationAlert('Hello JPush');
+
+        $this->payload_without_audience = $client->push()
+                                                 ->setPlatform('all')
+                                                 ->setNotificationAlert('Hello JPush');
+    }
+
+    public function testSimplePushToAll() {
+        $payload = $this->payload;
+        $result = $payload->build();
+
+        $this->assertTrue(is_array($result));
+        $this->assertEquals(4, count($result));
+        $this->assertArrayHasKey('platform', $result);
+        $this->assertArrayHasKey('audience', $result);
+        $this->assertArrayHasKey('notification', $result);
+        $this->assertArrayHasKey('options', $result);
+    }
+
+    public function testSetPlatform() {
+        $payload = $this->payload;
+
+        $result = $payload->build();
+        $this->assertEquals('all', $result['platform']);
+
+        $result = $payload->setPlatform('ios')->build();
+        $this->assertTrue(is_array($result['platform']));
+        $this->assertEquals(1, count($result['platform']));
+        $this->assertTrue(in_array('ios', $result['platform']));
+
+        $result = $payload->setPlatform(array('ios', 'android', 'blackberry'))->build();
+        $this->assertTrue(is_array($result['platform']));
+        $this->assertEquals(2, count($result['platform']));
+        $this->assertFalse(in_array('blackberry', $result['platform']));
+    }
+
+    public function testSetAudience() {
+        $result = $this->payload->build();
+        $this->assertEquals('all', $result['audience']);
+    }
+
+    public function testAddTag() {
+        $payload = $this->payload_without_audience;
+        $result = $payload->addTag('hello')->build();
+        $audience = $result['audience'];
+        $this->assertTrue(is_array($audience['tag']));
+        $this->assertEquals(1, count($audience['tag']));
+
+        $result = $payload->addTag(array('jpush', 'jiguang'))->build();
+        $this->assertEquals(3, count($result['audience']['tag']));
+    }
+    public function testAddTag2() {
+        $payload = $this->payload_without_audience;
+        $result = $payload->addTagAnd(array('jpush', 'jiguang'))->build();
+        $audience = $result['audience'];
+        $this->assertTrue(is_array($audience['tag_and']));
+        $this->assertEquals(2, count($audience['tag_and']));
+
+        $result = $payload->addTagAnd('hello')->build();
+        $this->assertEquals(3, count($result['audience']['tag_and']));
+    }
+
+    public function testAddTagAnd1() {
+        $payload = $this->payload_without_audience;
+        $result = $payload->addTagAnd('hello')->build();
+        $audience = $result['audience'];
+        $this->assertTrue(is_array($audience['tag_and']));
+        $this->assertEquals(1, count($audience['tag_and']));
+
+        $result = $payload->addTagAnd(array('jpush', 'jiguang'))->build();
+        $this->assertEquals(3, count($result['audience']['tag_and']));
+    }
+    public function testAddTagAnd2() {
+        $payload = $this->payload_without_audience;
+        $result = $payload->addTagAnd(array('jpush', 'jiguang'))->build();
+        $audience = $result['audience'];
+        $this->assertTrue(is_array($audience['tag_and']));
+        $this->assertEquals(2, count($audience['tag_and']));
+
+        $result = $payload->addTagAnd('hello')->build();
+        $this->assertEquals(3, count($result['audience']['tag_and']));
+    }
+
+    public function testAddRegistrationId1() {
+        $payload = $this->payload_without_audience;
+        $result = $payload->addRegistrationId('hello')->build();
+        $audience = $result['audience'];
+        $this->assertTrue(is_array($audience['registration_id']));
+        $this->assertEquals(1, count($audience['registration_id']));
+
+        $result = $payload->addRegistrationId(array('jpush', 'jiguang'))->build();
+        $this->assertEquals(3, count($result['audience']['registration_id']));
+    }
+    public function testAddRegistrationId2() {
+        $payload = $this->payload_without_audience;
+        $result = $payload->addRegistrationId(array('jpush', 'jiguang'))->build();
+        $audience = $result['audience'];
+        $this->assertTrue(is_array($audience['registration_id']));
+        $this->assertEquals(2, count($audience['registration_id']));
+
+        $result = $payload->addRegistrationId('hello')->build();
+        $this->assertEquals(3, count($result['audience']['registration_id']));
+    }
+
+    public function testSetNotificationAlert() {
+        $result = $this->payload->build();
+        $notification = $result['notification'];
+        $this->assertTrue(is_array($notification));
+        $this->assertEquals(1, count($notification));
+        $this->assertEquals('Hello JPush', $result['notification']['alert']);
+    }
+
+    public function testIosNotification() {
+        $payload = $this->payload;
+        $result = $payload->iosNotification()->build();
+        $ios = $result['notification']['ios'];
+        $this->assertTrue(is_array($ios));
+        $this->assertEquals(3, count($ios));
+        $this->assertArrayHasKey('alert', $ios);
+        $this->assertArrayHasKey('sound', $ios);
+        $this->assertArrayHasKey('badge', $ios);
+        $this->assertEquals('', $ios['alert']);
+        $this->assertEquals('', $ios['sound']);
+        $this->assertEquals('+1', $ios['badge']);
+
+        $result = $payload->iosNotification('hello')->build();
+        $ios = $result['notification']['ios'];
+        $this->assertEquals('hello', $result['notification']['ios']['alert']);
+    }
+    public function testIosNotificationWithArray() {
+        $payload = $this->payload;
+        $alert_array = array(
+            'alert_k1' => 'alert_v1',
+            'alert_k2' => 'alert_v2',
+            'alert_k3' => 'alert_v3',
+            'alert_k4' => 'alert_v4'
+        );
+        $array = array(
+            'sound' => 'jpush.caf',
+            'badge' => 2,
+            'content-available' => true,
+            'category' => 'jiguang',
+            'extras' => array(
+                'key' => 'value',
+                'jiguang'
+            ),
+            'invalid_key' => 'invalid_value'
+        );
+        $result = $payload->iosNotification($alert_array, $array)->build();
+        $ios = $result['notification']['ios'];
+        $this->assertTrue(is_array($ios['alert']));
+        $this->assertEquals(6, count($ios));
+        $this->assertFalse(array_key_exists('invalid_key', $ios));
+    }
+
+    public function testAndroidNotification() {
+        $payload = $this->payload;
+        $result = $payload->androidNotification()->build();
+        $android = $result['notification']['android'];
+        $this->assertTrue(is_array($android));
+        $this->assertEquals(1, count($android));
+        $this->assertArrayHasKey('alert', $android);
+        $this->assertEquals('', $android['alert']);
+
+        $result = $payload->androidNotification('hello')->build();
+        $android = $result['notification']['android'];
+        $this->assertEquals('hello', $result['notification']['android']['alert']);
+    }
+    public function testAndroidNotificationWithArray() {
+        $payload = $this->payload;
+        $array = array(
+            'title' => 'hello jpush',
+            'builder_id' => 2,
+            'extras' => array(
+                'key' => 'value',
+                'jiguang'
+            ),
+            'invalid_key' => 'invalid_value'
+        );
+        $result = $payload->androidNotification('', $array)->build();
+        $android = $result['notification']['android'];
+        $this->assertEquals(4, count($android));
+        $this->assertFalse(array_key_exists('invalid_key', $android));
+    }
+
+    public function testSetSmsMessage() {
+        $payload = $this->payload;
+        $smsMessage = array(
+            'delay_time' => 60,
+            'signid' => 154,
+            'temp_id' => 1,
+            'temp_para' => array(
+                'code' => 357
+            ),
+            'active_filter' => false
+        );
+        $result = $payload->setSmsMessage($smsMessage)->build();
+        $sms = $result['sms_message'];
+        $this->assertTrue(is_array($sms));
+        $this->assertEquals(5, count($sms));
+        $this->assertEquals(60, $sms['delay_time']);
+        $this->assertEquals(154, $sms['signid']);
+        $this->assertEquals(1, $sms['temp_id']);
+    }
+
+    public function testMessage() {
+        $payload = $this->payload;
+        $result = $payload->message('Hello JPush')->build();
+        $message = $result['message'];
+        $this->assertTrue(is_array($message));
+        $this->assertEquals(1, count($message));
+        $this->assertEquals('Hello JPush', $message['msg_content']);
+
+        $array = array(
+            'title' => 'hello jpush',
+            'content_type' => '',
+            'extras' => array(
+                'key' => 'value',
+                'jiguang'
+            ),
+            'invalid_key' => 'invalid_value'
+        );
+        $result = $payload->message('Hello JPush', $array)->build();
+    }
+
+    public function testOptions() {
+        $payload = $this->payload;
+        $result = $payload->options()->build();
+        $this->assertTrue(array_key_exists('options', $result));
+        $this->assertEquals(false, $result['options']['apns_production']);
+        $this->assertTrue(array_key_exists('sendno', $result['options']));
+
+        $array = array(
+            'sendno' => 100,
+            'time_to_live' => 100,
+            'apns_production' => true,
+            'override_msg_id' => 100,
+            'big_push_duration' => 100
+        );
+        $result = $payload->options($array)->build();
+        $options = $result['options'];
+        $this->assertEquals(5, count($options));
+        $this->assertArrayHasKey('apns_production', $options);
+        $this->assertEquals(true, $options['apns_production']);
+    }
+
+    public function testPushToAll() {
+        $payload = $this->payload;
+        $platform = array('ios', 'android', 'blackberry');
+        $ios_alert = array(
+            'k1' => 'v1',
+            'k2' => 'v2',
+            'k3' => 'v3',
+            'k4' => 'v4'
+        );
+        $ios_notification = array(
+            'sound' => 'jpush.caf',
+            'badge' => 2,
+            'content-available' => true,
+            'category' => 'jiguang',
+            'extras' => array(
+                'key' => 'value',
+                'jiguang'
+            ),
+            'invalid_key' => 'invalid_value'
+        );
+        $android_notification = array(
+            'title' => 'hello jpush',
+            'builder_id' => 2,
+            'extras' => array(
+                'key' => 'value',
+                'jiguang'
+            ),
+            'invalid_key' => 'invalid_value'
+        );
+        $message = array(
+            'title' => 'hello jpush',
+            'content_type' => '',
+            'extras' => array(
+                'key' => 'value',
+                'jiguang'
+            ),
+            'invalid_key' => 'invalid_value'
+        );
+
+        $result = $payload->setPlatform($platform)
+            ->iosNotification($ios_alert, $ios_notification)
+            ->androidNotification('Hello Android', $android_notification)
+            ->message('Hello JPush', $message)
+            ->build();
+
+        $response = $payload->send();
+        $this->assertEquals('200', $response['http_code']);
+
+        echo "HTTP HEADERS ARE: ";
+        print_r($response['headers']);
+
+        $body = $response['body'];
+        $this->assertTrue(is_array($body));
+        $this->assertEquals(2, count($body));
+        $this->assertArrayHasKey('sendno', $body);
+        $this->assertArrayHasKey('msg_id', $body);
+    }
+}

+ 77 - 0
vendor/jpush/jpush/tests/JPush/ReportPayloadTest.php

@@ -0,0 +1,77 @@
+<?php
+namespace JPush\Tests;
+use PHPUnit\Framework\TestCase;
+
+class ReportPayloadTest extends TestCase {
+
+    protected function setUp() {
+        global $client;
+        $this->payload = $client->push()
+                                ->setPlatform('all')
+                                ->addAllAudience()
+                                ->setNotificationAlert('Hello JPush');
+        $this->reporter = $client->report();
+    }
+
+    public function testPusher0() {
+        $payload = $this->payload;
+        $response = $payload->send();
+
+        $this->assertEquals('200', $response['http_code']);
+        $body = $response['body'];
+        $this->assertTrue(is_array($body));
+        $this->assertEquals(2, count($body));
+        $this->assertArrayHasKey('sendno', $body);
+        $this->assertArrayHasKey('msg_id', $body);
+        sleep(10);
+        return $body['msg_id'];
+    }
+    public function testPusher1() {
+        $payload = $this->payload;
+        $response = $payload->send();
+        $this->assertEquals('200', $response['http_code']);
+        sleep(10);
+        return $response['body']['msg_id'];
+    }
+
+    /**
+     * @depends testPusher0
+     * @depends testPusher1
+     */
+    public function testGetReceived($msg_id_0, $msg_id_1) {
+        $response = $this->reporter->getReceived($msg_id_0);
+        $this->assertEquals('200', $response['http_code']);
+        $body = $response['body'];
+        $this->assertTrue(is_array($body));
+        $this->assertEquals(1, count($body));
+        $this->assertTrue(is_array($body[0]));
+        $this->assertArrayHasKey('msg_id', $body[0]);
+
+        $response = $this->reporter->getReceived(array($msg_id_0, $msg_id_1));
+        $this->assertEquals('200', $response['http_code']);
+        $body = $response['body'];
+        $this->assertTrue(is_array($body));
+        $this->assertEquals(2, count($body));
+    }
+
+    /**
+     * @depends testPusher0
+     * @depends testPusher1
+     */
+    public function testGetMessages($msg_id_0, $msg_id_1) {
+        $response = $this->reporter->getMessages($msg_id_0);
+        $this->assertEquals('200', $response['http_code']);
+        $body = $response['body'];
+        $this->assertTrue(is_array($body));
+        $this->assertEquals(1, count($body));
+        $this->assertTrue(is_array($body[0]));
+        $this->assertEquals(4, count($body[0]));
+        $this->assertArrayHasKey('msg_id', $body[0]);
+
+        $response = $this->reporter->getMessages(array($msg_id_0, $msg_id_1));
+        $this->assertEquals('200', $response['http_code']);
+        $body = $response['body'];
+        $this->assertTrue(is_array($body));
+        $this->assertEquals(2, count($body));
+    }
+}

+ 18 - 0
vendor/jpush/jpush/tests/JPush/SchedulePayloadTest.php

@@ -0,0 +1,18 @@
+<?php
+namespace JPush\Tests;
+use PHPUnit\Framework\TestCase;
+
+class SchedulePayloadTest extends TestCase {
+
+    protected function setUp() {
+        global $client;
+        $this->schedule = $client->schedule();
+    }
+
+    public function testGetSchedules() {
+        $schedule = $this->schedule;
+        $response = $schedule->getSchedules();
+        $this->assertEquals('200', $response['http_code']);
+    }
+
+}

+ 8 - 0
vendor/jpush/jpush/tests/bootstrap.php

@@ -0,0 +1,8 @@
+<?php
+use JPush\Client;
+
+$app_key = getenv('app_key');
+$master_secret = getenv('master_secret');
+$client = new Client($app_key, $master_secret);
+
+$registration_id = getenv('registration_id');

+ 1 - 1
vendor/services.php

@@ -1,5 +1,5 @@
 <?php 
-// This file is automatically generated at:2023-02-23 15:55:26
+// This file is automatically generated at:2023-02-23 16:01:34
 declare (strict_types = 1);
 return array (
   0 => 'hg\\apidoc\\Service',