teamtools/php-sdk

teamtools API 的 PHP SDK

1.4.0 2017-01-27 13:23 UTC

README

安装

TeamTools PHP SDK 已在 Packagist 上:https://packagist.org.cn/packages/teamtools/php-sdk

可以使用 composer (https://getcomposer.org) 通过以下命令安装 TeamTools PHP SDK

composer require teamtools/php-sdk

所有依赖项将被导入到工作目录,您可以通过包含适当的文件开始使用 SDK。 示例: 如果您在与 vendor 目录同一级别的位置创建应用程序目录,并且您的目录结构如下所示

teamtools-php-sdk
├── app
│   └── index.php
├── vendor
├── composer.json
└── composer.lock

则您可以通过在 app/index.php 文件中包含 autoload.php 开始使用 teamtools SDK,如下所示

require '../vendor/autoload.php';

您不应该修改 vendor 目录的内容,因为这些内容将被 composer 更新覆盖。

注册客户端

在调用任何方法之前,客户端必须通过向静态方法 initialize 提供客户端凭证来进行身份验证,以与 API 一起工作。

use teamtools\TeamToolsClient;

TeamToolsClient::initialize([
    'client_id'     => 'your_api_client_id',
    'client_secret' => 'your_api_client_secret',
    'salt'          => 'your_salt'
]);

如果身份验证成功,从现在起我们可以调用 SDK 方法。

获取访问令牌

如果需要访问令牌来向 TeamTools API 发送更多请求,可以在注册客户端后检索它,如下所示

$accessToken = TeamToolsClient::getInstance()->getAccessToken();

客户实体

客户命名空间

要处理客户,请包含以下命名空间

use teamtools\Entities\Customer;
use teamtools\Exceptions\TTException;   // this will be needed for error-handling

创建客户

$data = [
    'name'    => 'Awesome customer',
    'email'   => 'customer@awesome.com',
    'phone'   => '+1234567890',
    'city'    => 'Berlin',
    'country' => 'Germany'
];

$customer = new Customer($data);

try {
    var_dump($customer->save(true));
} catch (TTException $ex) {
    echo $ex->getMessage();
}

更新客户

更新实体的流程是:从数据库中实例化对象,将其属性设置为所需值,并将其保存回数据库。实体可以通过 idtag 检索,或者进行搜索,在这种情况下将返回实体集合。检索实体的方式将在下一节(获取客户)中描述。

$customer = Customer::getByID('580a0ffcbffebc8b0e8b456a');
$customer->name = 'New Customer Name';

try {
    var_dump($customer->save());
} catch (TTException $ex) {
    echo $ex->getMessage();
}

获取客户

可以通过 id 获取单个客户对象。

try {
    $customer = Customer::getByID('580a0ffcbffebc8b0e8b456a');
    var_dump($customer);
} catch (TTException $ex) {
    echo $ex->getMessage();
}

也可以通过标签检索实体,在这种情况下将返回实体集合。

try {
    $customers = $customer = Customer::getByTag('new');
    var_dump($customers);
} catch (TTException $ex) {
    echo $ex->getMessage();
}

最后,实体可以通过使用所有实体中提供的静态方法 getAll 使用关键字进行搜索,该方法返回实体集合。

// all customers
$customers = Customer::getAll();

foreach ($customers as $customer) {
    var_dump($customer->name);
}

// search customers for 'awesome' in searchable attributes
$customers = Customer::getAll(['keyword' => 'awesome']);

foreach ($customers as $customer) {
    var_dump($customer->name);
}

删除客户

通过从数据库中实例化它并调用其 delete 方法来删除客户。数据正在被软删除。

try {
    $customer = Customer::getByID('580a0ffcbffebc8b0e8b456aff');
    var_dump($customer->delete());
} catch (TTException $ex) {
    echo $ex->getMessage();
}

将最终用户迁移到另一个客户

try {
    $customer = Customer::getByID('57e3a147bffebc75388b4571');
    $newCustomerId = '57ecf1f6bffebcc5098b4585';

    //migrate specific endusers
    $ids = ['57ecf1b0bffebcc3098b4582', '57ecf1b0bffebcc3098b4587'];

    var_dump($customer->migrateEndusers($newCustomerId, $ids));
} catch (TTException $ex) {
    echo $ex->getMessage();
}
try {
    $customer = Customer::getByID('57e3a147bffebc75388b4571');
    $newCustomerId = '57ecf1f6bffebcc5098b4585';

    //migrate all endusers

    var_dump($customer->migrateEndusers($newCustomerId));
} catch (TTException $ex) {
    echo $ex->getMessage();
}

获取客户的最终用户

try {
    $customer = Customer::getByID('582191a10957473545bdff43');
    $endUsers = $customer->getEndUsers();

    var_dump($endUsers);
} catch (TTException $ex) {
    echo $ex->getMessage();
}

获取客户的事件

try {
    $customer = Customer::getByID('57fbe76c0957475156bdff59');
    $events = $customer -> getEvents();

    var_dump($events);
} catch (TTException $ex) {
    echo $ex->getMessage();
}

恢复已删除客户

try {
    var_dump(Customer::restore('57fce361bffebc231c8b45cb'));
} catch (TTException $ex) {
    echo $ex->getMessage();
}

恢复已删除最终用户

try {
    var_dump(EndUser::restore('5822eaccbffebcaa088b458e'));
} catch (TTException $ex) {
    echo $ex->getMessage();
}

属性

属性是可以定义并附加到实体的属性。每个实体都有一组预定义的属性,可以创建任意数量的额外用户定义属性。

获取客户属性

检索实体的属性列表。包含默认属性和自定义属性,以及与其他实体之间关系的描述。

Customer::getAttributes();

创建或更新客户属性

可以通过实例化具有相应属性的 Attribute 对象并在相应的实体上调用 saveAttribute 方法来定义自定义属性,如下所示。新的自定义属性 department 将被创建并附加到 Customer 上。在处理 Customer 实体时,此属性将包含在验证中。例如:创建此属性后,如果未提供 department,则无法创建 Customer 实体,因为 department 是必需的自定义属性(《required` => true))。

$data = [
    'name'         => 'department',
    'prettyName'   => 'Department',
    'type'         => 'text',
    'description'  => "Customer's department",
    'required'     => true,
    'editable'     => true,
    'searchable'   => true,
    'default'      => false,
    'defaultValue' => '',
    'unique'       => false
];

$attribute = new Attribute($data);

try {
    Customer::saveAttribute($attribute);
} catch (TTException $ex) {
    echo $ex->getMessage();
}
参数说明

删除客户属性

可以通过向相应实体的静态方法 deleteAttribute 提供其 id 来删除属性。属性是软删除的,即记录被标记为已删除,但不会从数据库中物理删除。

try {
    Customer::deleteAttribute('56571718095747cc4b9215f4');
} catch (TTException $ex) {
    echo $ex->getMessage();
}

获取最终用户属性

检索实体的属性列表。包含默认属性和自定义属性,以及与其他实体之间关系的描述。

EndUser::getAttributes();

创建或更新最终用户属性

可以通过实例化具有相应属性的 Attribute 对象并在相应的实体上调用 saveAttribute 方法来定义自定义属性,如下所示。新的自定义属性 testAttribute 将被创建并附加到 EndUser 上。在处理 EndUser 实体时,此属性将包含在验证中。例如:创建此属性后,如果未提供 testAttribute,则无法创建 EndUser 实体,因为 testAttribute 是必需的自定义属性(《required` => true))。

$data = [
    'name'         => 'testAttribute',
    'prettyName'   => 'Test attribute',
    'type'         => 'text',
    'description'  => "EndUser's test attribute",
    'required'     => true,
    'editable'     => true,
    'searchable'   => true,
    'default'      => false,
    'defaultValue' => '',
    'unique'       => false
];

$attribute = new Attribute($data);

try {
    EndUser::saveAttribute($attribute);
} catch (TTException $ex) {
    echo $ex->getMessage();
}

删除最终用户属性

可以通过向相应实体的静态方法 deleteAttribute 提供其 id 来删除属性。属性是软删除的,即记录被标记为已删除,但不会从数据库中物理删除。

try {
    EndUser::deleteAttribute('56571718095747cc4b9215f4');
} catch (TTException $ex) {
    echo $ex->getMessage();
}

TeamTools SDK 响应格式

与 TeamTools SDK 的每次交互都会返回响应,即使删除操作返回已删除的资源。有两种类型的响应:PHP 对象和 API 返回的原始 JSON 响应。默认格式是 PHP 对象(当返回集合时为实体或 ArrayIterator)和原始响应可以通过提供 true 给实例方法来接收。

  • 给实例方法提供 true

    • 更新客户并返回原始响应
      try {
          $customer       = Customer::getByID('56582c53095747b64b9215f7');
          $customer->name = 'SDK awesome customer';
      
          $response   = $customer->save(true);
      } catch (TTException $ex) {
          echo $ex->getMessage();
      }
    • 更新客户并返回 teamtools\Entities\Customer 对象
      try {
          $customer       = Customer::getByID('56582c53095747b64b9215f7');
          $customer->name = 'SDK awesome customer';
      
          $response   = $customer->save();
      } catch (TTException $ex) {
          echo $ex->getMessage();
      }
  • 当使用静态方法时,调用带有后缀 Raw 的方法

    • $customer = Customer::getByID('565719f3095747906a9215f5'); - 返回 teamtools\Entities\Customer 对象
    • $customer = Customer::getByIDRaw('565719f3095747906a9215f5'); - 返回原始 JSON 响应
具有相应 "原始响应" 方法的函数
            |

在响应中嵌入相关对象

通常,相关对象将用 ID 表示。例如,响应中的客户将包含订阅 ID,可用于获取订阅对象。可以将相关对象直接嵌入到响应中,从而节省额外的服务器请求。

将订阅对象嵌入到客户响应中的示例

try {
    $customer = Customer::getByID('5739c7fbbffebc4c0b8b4567', 'subscription');
    var_dump($customer);
} catch (TTException $ex) {
    echo $ex->getMessage();
}

相关数据可以嵌套,并且可以包含多个关系。参数格式应该是包含要嵌入的关系的逗号分隔的字符串。

包含参数的示例

  • 嵌入单个关系
    • include=events
  • 嵌入多个关系
    • include=events,customer
  • 嵌套数据
    • include=events,customer.invoices

一些相关对象操作的示例(为了清晰,未在 try-catch 块中包装)

// retrieve all features from package that customer is currently subscribed to:
$customer = Customer::getByID('5739c7fbbffebc4c0b8b4567', 'subscription.package.features');
var_dump($customer->subscription->package->features);

// change property of related object
$customer = Customer::getByID('5739c7fbbffebc4c0b8b4567', 'subscription.package');
$package = $customer->subscription->package;
$package->name = 'Pro plan changed name';

var_dump($package->save());

// include more than one relation and response examples
$customer = Customer::getByID('5739c7fbbffebc4c0b8b4567', 'subscription.package,users');
var_dump($customer);
var_dump($customer->subscription);
var_dump($customer->subscription->package);
var_dump($customer->users);

// search and include
$customers = Customer::getAll([
    'filter'  => 'country{ct}jamaica',
    'include' => 'subscription.package'
]);

var_dump($customers);

功能

功能命名空间

要使用功能,请包含以下命名空间

use teamtools\Entities\Feature;
use teamtools\Exceptions\TTException;   // this will be needed for error-handling

获取功能属性

$attributes = Feature::getAttributes();

创建功能属性

use teamtools\Entities\Feature;
use teamtools\Entities\Attribute;

$data = [
    'name'         => 'status',
    'prettyName'   => 'Feature status',
    'type'         => 'number',
    'description'  => 'Status of feature',
    'required'     => true,
    'editable'     => true,
    'searchable'   => true,
    'default'      => false,
    'defaultValue' => ''
];

try {
    $attribute = new Attribute($data);
    Feature::saveAttribute($attribute);
} catch (TTException $ex) {
    echo $ex->getMessage();
}

更新功能属性

use teamtools\Entities\Feature;
use teamtools\Entities\Attribute;

$data = [
    'id'           => '5656c899bffebc47078b456e',
    'name'         => 'status',
    'prettyName'   => 'Feature status',
    'type'         => 'number',
    'description'  => 'Status of feature. 1 - active; 0 - inactive.',
    'required'     => true,
    'editable'     => true,
    'searchable'   => true,
    'default'      => false,
    'defaultValue' => ''
];

try {
    $attribute = new Attribute($data);
    Feature::saveAttribute($attribute);
} catch (TTException $ex) {
    echo $ex->getMessage();
}

删除功能属性

try {
    Feature::deleteAttribute('5656c899bffebc47078b456e');
} catch (TTException $ex) {
    echo $ex->getMessage();
}

通过 ID 获取功能

try {
    $feature = Feature::getByID('5655c5f6bffebc40078b459e');
} catch (TTException $ex) {
    echo $ex->getMessage();
}

通过标签获取功能

try {
    $feature = Feature::getByTag('master');
} catch (TTException $ex) {
    echo $ex->getMessage();
}

创建功能

$data = [
    'name'        => 'Feature B',
    'description' => 'Feature B',
    'uniqueKey'   => 'feat-B'
];

try {
    $feature = new Feature($data);
    $feature->save();
} catch (TTException $ex) {
    echo $ex->getMessage();
}

更新功能

$feature              = Feature::getByID('5655c5f6bffebc40078b459e');
$feature->description = 'Feature B - extended trial period.';

try {
    $feature->save();
} catch (TTException $ex) {
    echo $ex->getMessage();
}

删除功能

try {
    $feature = Feature::getByID('5655d765bffebc3f078b4595');
    $feature->delete();
} catch (TTException $ex) {
    echo $ex->getMessage();
}

关系示例

更新功能依赖关系
try {
    $feature                 = Feature::getByID('5655c5edbffebc40078b459c');
    $feature->dependency_ids = ['5655c5f6bffebc40078b459e'];
    $feature->save();
} catch (TTException $ex) {
    echo $ex->getMessage();
}
删除功能依赖关系
try {
    $feature                 = Feature::getByID('5655c5edbffebc40078b459c');
    $feature->dependency_ids = [];
    $feature->save();
} catch (TTException $ex) {
    echo $ex->getMessage();
}

组、套餐和计划

组、套餐和计划命名空间

要使用组、套餐或计划,请包含相应的命名空间

use teamtools\Entities\Group;
use teamtools\Entities\Package;
use teamtools\Entities\Plan;

步骤 1:创建组

组具有以下参数

  • name - 组的用户友好标签,您将在仪表板中看到它,也许您的客户也会看到。
  • default - 应根据您是否希望将组设置为默认值来设置为 true 或 false。
  • defaultPackageId - 每个组应包含至少一个套餐。如果组包含多个套餐,则应确定哪个套餐是默认的 defaultPackageId

代码示例

$data = [
    'name'    => 'Standard group',
    'default' => true   //if ommited and this is first group in the system, group will become default
];

$group = new Group($data);

try {
    var_dump($group->save());
} catch (TTException $ex) {
    echo $ex->getMessage();
}

使用默认包并分配为默认组

$data = [
    'name'           => 'Basic group',
    'defaultPackage' => '5733052dbffebc46088b456b',
    'default'        => true
];

$group = new Group($data);

try {
    var_dump($group->save());
} catch (TTException $ex) {
    echo $ex->getMessage();
}

按组ID检索包

try {
    $group = Group::getByID('573301dbbffebc46088b4567');
    var_dump($group->getPackages());
} catch (TTException $ex) {
    echo $ex->getMessage();
}

步骤 2:创建包

包具有以下参数

  • 名称 - 包的用户友好标签,您将在仪表板中看到,可能您的客户也会看到。
  • 描述 - 对包的额外描述,提供更多信息。
  • 默认 - 表示包是否为组的默认值。
  • groupId - 表示包组。
  • featureIds - 表示要分配给包的功能。

代码示例

$data = [
    'name'    => 'Basic package',
    'groupId' => '573301dbbffebc46088b4567',
    'default' => 'true'     // assign this package as default in its group
];

$package = new Package($data);

try {
    var_dump($package->save());
} catch (TTException $ex) {
    echo $ex->getMessage();
}

示例:创建带有功能的包

$data = [
    'name'       => 'Pro package',
    'featureIds' => [
        '573305cdbffebc46088b4571',
        '573305e5bffebc46088b4575'
    ],
    'groupId'    => '573301dbbffebc46088b4567'
];

$package = new Package($data);

try {
    var_dump($package->save());
} catch (TTException $ex) {
    echo $ex->getMessage();
}

创建包时,您将从teamtools获得packageId。每个包都需要一个唯一的ID。您将提供此值在API请求中订阅客户的某个包。

默认包

如果在组中仅创建了一个包,则此包将获得defaultPackageId。如果有两个或更多包在组中创建,您需要决定哪个包成为默认值。

检索所有包

try {
    $packages = Package::getAll();
    
    var_dump($packages);
} catch (TTException $ex) {
    echo $ex->getMessage();
}

步骤 3:创建计划

计划包括以下参数

  • 名称 - 计划的用户友好标签,将继承自包名称
  • 描述 - 对计划的额外描述,提供更多信息,将继承自包名称
  • 试用期 - 可用于试用的天数,如果您的服务提供试用期。
  • initialFee - 金额,如果想要为服务设置收取特定费用。
  • 定价 - 如下所述

示例:创建单位计划

$data = [
    'packageId' => '57330639bffebc46088b4579',
    'trial'     => '30',
    'currency'  => 'USD',
    'pricing'   => [
        'type' => 'unit',
        'interval' => [
            'type' => 'month',
            'amount' => 2
        ],
        'unit'   => 'enduser',
        'amount' =>  200    //amount in cents
    ]
];

$plan = new Plan($data);

try {
    var_dump($plan->save());
} catch (TTException $ex) {
    echo $ex->getMessage();
}

示例:创建固定计划

$data = [
    'name'      => 'Enterprise',
    'packageId' => '57330639bffebc46088b4579',
    'trial' => '30',
    'currency'  => 'USD',
    'pricing'   => [
        'type' => 'flat',
        'interval' => [
            'type'   => 'month',
            'amount' => 2
        ],
        'amount' =>  1500
    ]
];

示例:创建层计划

$data = [
    'packageId' => '57330639bffebc46088b4579',
    'trial'     => '30',
    'currency'  => 'USD',
    'pricing'   => [
        'type' => 'tier',
        'interval' => [
            'type' => 'month',
            'amount' => 2
        ],
        'unit' => 'enduser',
        'levels' => [
            [
                'condition' => [
                    'min' => 1,
                    'max' => -1
                ],
                'expression' => [
                    [
                        'type'   => 'unit',
                        'unit'   => 'enduser',
                        'amount' => 120     //amount in cents
                    ]
                ]
            ]
        ]
    ]
];

$plan = new Plan($data);

try {
    var_dump($plan->save());
} catch (TTException $ex) {
    echo $ex->getMessage();
}

按ID获取计划

try {
    $plan = Plan::getByID('5673eff3bffebc4e078b4569');
} catch (TTException $ex) {
    echo $ex->getMessage();
}

开始订阅客户到包

有两种方式创建客户订阅:通过客户创建/更新请求和通过专用端点。

使用客户更新请求创建订阅(响应中返回 customer

try {
    $customer = Customer::getByID('5730838fbffebc290b8b4591');
    $customer->groupId = 'default';

    var_dump($customer->save());
} catch (TTException $ex) {
    echo $ex->getMessage();
}

使用专用端点创建订阅(默认组)。响应中返回 subscription

try {
    $customer = Customer::getByID('5730838fbffebc290b8b4591');

    $subscriptionData = [
        'groupId' => 'default'
    ];

    var_dump($customer->subscribe($subscriptionData));
} catch (TTException $ex) {
    echo $ex->getMessage();
}

使用专用端点创建订阅

try {
    $customer = Customer::getByID('5730838fbffebc290b8b4591');

    $subscriptionData = [
        'groupId'     => '573301dbbffebc46088b4567',
        'packageId'   => '5733052dbffebc46088b456b',
        'manual'      => 'false',
        'stripeToken' => 'xxxx',
        'force'       => false
    ];

    var_dump($customer->subscribe($subscriptionData));
} catch (TTException $ex) {
    echo $ex->getMessage();
}

检索客户的订阅

try {
    $customer = Customer::getByID('5730838fbffebc290b8b4591');
    var_dump($customer->getSubscription());
} catch (TTException $ex) {
    echo $ex->getMessage();
}

从包中取消客户的订阅

通过调用以下SDK函数,客户将从当前包中取消订阅。如果订阅存在于支付网关上,它也将被取消。返回值:subscription 对象。

try {
    $customer = Customer::getByID('56c73ce5bffebc47078b4619');
    var_dump($customer->unsubscribe());
} catch (TTException $ex) {
    echo $ex->getMessage();
}

添加发票项目

可以添加和收集发票项目,以便在下一次发票生成时使用。如果订阅存在于支付网关上,将在网关上创建发票项目。否则,它将在TeamTools数据库中创建。

use teamtools\Entities\Subscription;

$data = [
    'description' => 'This item will appear on next invoice',
    'currency'    => 'usd',
    'amount'      => 1800
];

try {
    $subscription = Subscription::getByID('56cc46f2bffebc5b078b4571');
    $subscription->addInvoiceItem($data);
} catch (TTException $ex) {
    echo $ex->getMessage();
}

发票

按ID获取发票

use teamtools\Entities\Invoice;

try {
    $invoice = Invoice::getByID('56cc581abffebc5b078b4575');

    var_dump($invoice);
} catch (TTException $ex) {
    echo $ex->getMessage();
}

创建发票

use teamtools\Entities\Invoice;

$data = [
    'invoiceDate' => '2016-01-22',
    'dueDate'     => '2016-02-22',
    'customerId'  => '56c73ce5bffebc47078b4619',
    'items'       => [
        [
            'description' => 'Initial account setup',
            'amount'      => 1750
        ],
        [
            'description' => 'Application adjustments',
            'amount'      => 450000
        ]
    ]
];

$invoice = new Invoice($data);

try {
    var_dump($invoice->save());
} catch (TTException $ex) {
    echo $ex->getMessage();
}

结算发票

用于手动标记发票为已结算。

use teamtools\Entities\Invoice;

try{
    $invoice = Invoice::getByID('56cc581abffebc5b078b4575');
    $invoice->settle();
    var_dump($invoice->save());
} catch (TTException $ex) {
    echo $ex->getMessage();
}

在发票上应用支付

手动将付款应用于发票总额。如果应用金额等于发票总额,则发票将被标记为已支付。如果金额大于未结发票金额,则发票将被关闭,剩余金额将添加到订阅对象的余额中。

use teamtools\Entities\Invoice;

try {
    $invoice = Invoice::getByID('56cc581abffebc5b078b4575');
    $invoice->applyPayment(['amount' => 350]);
    var_dump($invoice->save());
} catch (TTException $ex) {
    echo $ex->getMessage();
}

获取支付/退款

检索发票的退款或支付

try {
    $invoice = Invoice::getByID('57e3a348bffebc83318b457e');

    var_dump($invoice->getRefunds());
    var_dump($invoice->getPayments());
} catch (TTException $ex) {
    echo $ex->getMessage();
}

批量插入和更新

客户和最终用户支持批量操作,如通过单个请求插入和更新多个记录。为此操作,应提供名为 "data" 的结构,其中包含要持久化的实体数组。如果数组元素包含 "id" 元素,则将更新具有该特定ID的实体。否则,将插入实体。所有验证仍然有效,就像处理单个实体时一样。

客户示例

use teamtools\Entities\Customer;

$customers = [
    [
        'id'      => '5704f67cbffebc47078b4574',
        'name'    => 'My Customer XXY',
        'email'   => 'customerCHANGE@email.com',
        'phone'   => '+1234123412',
        'country' => 'USA',
        'city'    => 'Chicago',
    ],
    [
        'name'    => 'My Customer YXY',
        'email'   => 'customer@email.com',
        'phone'   => '+1234123412',
        'country' => 'USA',
        'city'    => 'Chicago'
    ]
];

try {
    var_dump(Customer::saveAll($customers, false));
} catch (TTException $ex) {
    echo $ex->getMessage();
}

最终用户示例

use teamtools\Entities\EndUser;

$endusers = [
    [
        'firstName'  => 'Mary',
        'lastName'   => 'Jones',
        'email'      => 'customerCHANGE@email.com',
        'phone'      => '+1234123412',
        'country'    => 'USA',
        'city'       => 'Chicago',
        'customerId' => '5704f67cbffebc47078b4574'
    ],
    [
        'firstName' => 'Peter',
        'lastName'  => 'Johnson',
        'email'     => 'customer@email.com',
        'phone'     => '+1234123412',
        'country'   => 'USA',
        'city'      => 'Chicago',
        'customerId' => '5704f67cbffebc47078b4574'
    ],
    [
        'id'        => '57050433bffebc46078b457f',
        'firstName' => 'John',
        'lastName'  => 'Smith',
        'email'     => 'customer@email.com',
        'phone'     => '+1234123412',
        'country'   => 'USA',
        'city'      => 'Chicago',
        'customerId' => '5704f67cbffebc47078b4574'
    ]
];

try {
    var_dump(EndUser::saveAll($endusers, false));
} catch (TTException $ex) {
    echo $ex->getMessage();
}

检索webhook事件

try {
    $webEvent = WebEvent::getByID('57334232bffebc77088b4574');
    var_dump($webEvent);
} catch (TTException $ex) {
    echo $ex->getMessage();
}

Webhook事件格式示例

客户名称已更新

{
  "data": {
    "id": "5729eb7bbffebc48088b456e",
    "timestamp": "2016-05-04 12:30:51",
    "source": "UI",
    "memberId": "5729c6ebbffebc47088b458a",
    "url": null,
    "action": "updated",
    "data": {
      "type": "customer",
      "value": {
        "id": "5729e7c8bffebc47088b458b",
        "name": "ShiftPlanning 2",
        "email": "sp@shiftplanning.com",
        "country": "USA",
        "phone": "123",
        "city": "Belgrade",
        "joinDate": {
          "date": "2016-05-01 00:00:00.000000",
          "timezone_type": 3,
          "timezone": "UTC"
        },
        "updated_at": {
          "date": "2016-05-04 12:30:51.000000",
          "timezone_type": 3,
          "timezone": "UTC"
        },
        "created_at": {
          "date": "2016-05-04 12:15:04.000000",
          "timezone_type": 3,
          "timezone": "UTC"
        },
        "tags": [],
        "notes": []
      },
      "old": {
        "id": "5729e7c8bffebc47088b458b",
        "name": "ShiftPlanning",
        "email": "sp@shiftplanning.com",
        "country": "USA",
        "phone": "123",
        "city": "Belgrade",
        "joinDate": {
          "date": "2016-05-01 00:00:00.000000",
          "timezone_type": 3,
          "timezone": "UTC"
        },
        "updated_at": {
          "date": "2016-05-04 12:15:04.000000",
          "timezone_type": 3,
          "timezone": "UTC"
        },
        "created_at": {
          "date": "2016-05-04 12:15:04.000000",
          "timezone_type": 3,
          "timezone": "UTC"
        },
        "tags": [],
        "notes": []
      }
    },
    "status": "failed",
    "updated_at": {
      "date": "2016-05-04 12:30:51.000000",
      "timezone_type": 3,
      "timezone": "UTC"
    },
    "created_at": {
      "date": "2016-05-04 12:30:51.000000",
      "timezone_type": 3,
      "timezone": "UTC"
    }
  }
}

已创建组

{
  "data": {
    "id": "57332e6dbffebc78088b4573",
    "timestamp": "2016-05-11 13:06:53",
    "source": "API",
    "memberId": null,
    "url": null,
    "action": "created",
    "data": {
      "type": "group",
      "value": {
        "id": "57332e6dbffebc78088b4571",
        "default": true,
        "updated_at": {
          "date": "2016-05-11 13:06:53.000000",
          "timezone_type": 3,
          "timezone": "UTC"
        },
        "created_at": {
          "date": "2016-05-11 13:06:53.000000",
          "timezone_type": 3,
          "timezone": "UTC"
        },
        "tags": [],
        "defaultPackageId": null
      },
      "old": null
    },
    "status": "failed",
    "updated_at": {
      "date": "2016-05-11 13:06:53.000000",
      "timezone_type": 3,
      "timezone": "UTC"
    },
    "created_at": {
      "date": "2016-05-11 13:06:53.000000",
      "timezone_type": 3,
      "timezone": "UTC"
    }
  }
}

包已删除

{
  "data": {
    "id": "57334232bffebc77088b4574",
    "timestamp": "2016-05-11 14:31:14",
    "source": "API",
    "memberId": null,
    "url": null,
    "action": "deleted",
    "data": {
      "type": "package",
      "value": {
        "id": "5733052dbffebc46088b456b",
        "name": "Basic package",
        "default": false,
        "updated_at": {
          "date": "2016-05-11 10:10:53.000000",
          "timezone_type": 3,
          "timezone": "UTC"
        },
        "created_at": {
          "date": "2016-05-11 10:10:53.000000",
          "timezone_type": 3,
          "timezone": "UTC"
        },
        "groupId": "573301dbbffebc46088b4567",
        "deleted_at": "2016-05-11 14:31:14",
        "tags": [],
        "featureIds": []
      },
      "old": null
    },
    "status": "failed",
    "updated_at": {
      "date": "2016-05-11 14:31:14.000000",
      "timezone_type": 3,
      "timezone": "UTC"
    },
    "created_at": {
      "date": "2016-05-11 14:31:14.000000",
      "timezone_type": 3,
      "timezone": "UTC"
    }
  }
}