diff --git a/dingdingcallback/api/Activate.php b/dingdingcallback/api/Activate.php
new file mode 100644
index 00000000..f3770a41
--- /dev/null
+++ b/dingdingcallback/api/Activate.php
@@ -0,0 +1,60 @@
+errcode != 0)
+ {
+ exit("Failed: " . json_encode($res));
+ }
+ }
+}
diff --git a/dingdingcallback/api/Auth.php b/dingdingcallback/api/Auth.php
new file mode 100644
index 00000000..dd100661
--- /dev/null
+++ b/dingdingcallback/api/Auth.php
@@ -0,0 +1,107 @@
+ 'jsapi', 'access_token' => $accessToken));
+ self::check($response);
+ $jsticket = $response->ticket;
+ Cache::setJsTicket('js_ticket_'.$corpId,$jsticket);
+ }
+
+ return $jsticket;
+ }
+
+
+ function curPageURL()
+ {
+ $pageURL = 'http';
+
+ if (array_key_exists('HTTPS',$_SERVER)&&$_SERVER["HTTPS"] == "on")
+ {
+ $pageURL .= "s";
+ }
+ $pageURL .= "://";
+
+ if ($_SERVER["SERVER_PORT"] != "80")
+ {
+ $pageURL .= $_SERVER["SERVER_NAME"] . ":" . $_SERVER["SERVER_PORT"] . $_SERVER["REQUEST_URI"];
+ }
+ else
+ {
+ $pageURL .= $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"];
+ }
+ return $pageURL;
+ }
+
+ public static function isvConfig($corpId)
+ {
+ $corpInfo = ISVClass::getCorpInfo($corpId);
+ $corpId = $corpInfo['corp_id'];
+ $agentId = ISVService::getCurAgentId($corpId,APPID);
+ $nonceStr = 'abcdefg';
+ $timeStamp = time();
+ $url = self::curPageURL();
+ $ticket = self::getTicket($corpId,$corpInfo['corpAccessToken']);
+ $signature = self::sign($ticket, $nonceStr, $timeStamp, $url);
+ $arr = array();
+ $arr['ticket'] = $ticket;
+ $arr['nonceStr'] = $nonceStr;
+ $arr['timeStamp'] = $timeStamp;
+ $arr['url'] = $url;
+ $arr['signature'] = $signature;
+
+ $config = array(
+ 'url' => $url,
+ 'nonceStr' => $nonceStr,
+ 'agentId' => $agentId,
+ 'timeStamp' => $timeStamp,
+ 'corpId' => $corpId,
+ 'suite_key' => SUITE_KEY,
+ 'signature' => $signature);
+ return json_encode($config, JSON_UNESCAPED_SLASHES);
+ }
+
+ public static function sign($ticket, $nonceStr, $timeStamp, $url)
+ {
+ $plain = 'jsapi_ticket=' . $ticket .
+ '&noncestr=' . $nonceStr .
+ '×tamp=' . $timeStamp .
+ '&url=' . $url;
+ return sha1($plain);
+ }
+
+ /**
+ * @param $accessToken
+ * @param $code
+ * @return 个人授权信息
+ */
+ public static function getPerson($accessToken, $code)
+ {
+ $response = Http::get("/user/get_private_info",
+ array("access_token" => $accessToken, "tmp_auth_code" => $code));
+ return json_encode($response);
+ }
+
+
+ static function check($res)
+ {
+ if ($res->errcode != 0)
+ {
+ Log::e("FAIL: " . json_encode($res));
+ exit("Failed: " . json_encode($res));
+ }
+ }
+}
diff --git a/dingdingcallback/api/Chat.php b/dingdingcallback/api/Chat.php
new file mode 100644
index 00000000..4910bd86
--- /dev/null
+++ b/dingdingcallback/api/Chat.php
@@ -0,0 +1,38 @@
+ $accessToken),
+ json_encode($chatOpt));
+ return $response;
+ }
+
+ public static function bindChat($accessToken, $chatid,$agentid)
+ {
+ $response = Http::get("/chat/bind",
+ array("access_token" => $accessToken,"chatid"=>$chatid,"agentid"=>$agentid));
+ return $response;
+ }
+
+ public static function sendmsg($accessToken, $opt)
+ {
+ $response = Http::post("/chat/send",
+ array("access_token" => $accessToken),
+ json_encode($opt));
+ return $response;
+ }
+
+ public static function callback($accessToken, $opt)
+ {
+ $response = Http::post("/call_back/register_call_back",
+ array("access_token" => $accessToken),
+ json_encode($opt));
+ return $response;
+ }
+}
\ No newline at end of file
diff --git a/dingdingcallback/api/Department.php b/dingdingcallback/api/Department.php
new file mode 100644
index 00000000..809315a3
--- /dev/null
+++ b/dingdingcallback/api/Department.php
@@ -0,0 +1,28 @@
+ $accessToken),
+ json_encode($dept));
+ return $response->id;
+ }
+
+
+ public static function listDept($accessToken)
+ {
+ $response = Http::get("/department/list",
+ array("access_token" => $accessToken));
+ return $response->department;
+ }
+
+
+ public static function deleteDept($accessToken, $id)
+ {
+ $response = Http::get("/department/delete",
+ array("access_token" => $accessToken, "id" => $id));
+ return $response->errcode == 0;
+ }
+}
\ No newline at end of file
diff --git a/dingdingcallback/api/ISVClass.php b/dingdingcallback/api/ISVClass.php
new file mode 100644
index 00000000..b06dfea4
--- /dev/null
+++ b/dingdingcallback/api/ISVClass.php
@@ -0,0 +1,48 @@
+errcode != 0)
+ {
+ exit("Failed: " . json_encode($res));
+ }
+}
diff --git a/dingdingcallback/api/ISVService.php b/dingdingcallback/api/ISVService.php
new file mode 100644
index 00000000..34e63ae7
--- /dev/null
+++ b/dingdingcallback/api/ISVService.php
@@ -0,0 +1,216 @@
+ SUITE_KEY,
+ "suite_secret" => SUITE_SECRET,
+ "suite_ticket" => $suiteTicket
+ )));
+ self::check($response);
+ $suiteAccessToken = $response->suite_access_token;
+ Cache::setSuiteAccessToken($suiteAccessToken);
+ }
+ return $suiteAccessToken;
+ }
+
+ public static function getCorpInfoByCorId($corpId){
+ $corpList = json_decode(Cache::getCorpInfo(),true);
+ if(!is_array($corpList)){
+ return false;
+ }
+
+ foreach($corpList as $corp){
+ if($corp['corp_id']==$corpId){
+ return $corp;
+ }
+ }
+ }
+
+ public static function getCorpInfoByTmpCode($code){
+ $corpList = json_decode(Cache::getCorpInfo(),true);
+ if(!is_array($corpList)){
+ return false;
+ }
+
+ foreach($corpList as $corp){
+ if($corp['tmp_auth_code']==$code){
+ return $corp;
+ }
+ }
+ }
+
+ public static function getPermanentCodeInfo($suiteAccessToken,$tmpAuthCode)
+ {
+ $permanentCodeInfo = json_decode(ISVService::getCorpInfoByTmpCode($tmpAuthCode));
+
+ if (!$permanentCodeInfo)
+ {
+ $permanentCodeResult = Http::post("/service/get_permanent_code",
+ array(
+ "suite_access_token" => $suiteAccessToken
+ ),
+ json_encode(array(
+ "tmp_auth_code" => $tmpAuthCode
+ )));
+ self::check($permanentCodeResult);
+ $permanentCodeInfo = self::savePermanentCodeInfo($permanentCodeResult,$tmpAuthCode);
+ }
+ return $permanentCodeInfo;
+ }
+
+ public static function savePermanentCodeInfo($permanentCodeInfo,$tmpAuthCode){
+ $arr = array();
+ $arr['corp_name'] = $permanentCodeInfo->auth_corp_info->corp_name;
+ $arr['corp_id'] = $permanentCodeInfo->auth_corp_info->corpid;
+ $arr['permanent_code'] = $permanentCodeInfo->permanent_code;
+ $arr['tmp_auth_code'] = $tmpAuthCode;
+ $corpInfo = json_decode(Cache::getCorpInfo());
+ if(!$corpInfo){
+ $corpInfo = array();
+ }
+
+ $corpExist = false;
+ foreach($corpInfo as $cp){
+ if($cp->corp_id == $arr['corp_id']){
+ $corpExist = true;
+ }
+ }
+
+ if(!$corpExist){
+ $corpInfo[] = $arr;
+ Cache::setCorpInfo(json_encode($corpInfo));
+ }
+ return $arr;
+ }
+
+ public static function getCurAgentId($corpId,$appId){
+ $authInfo = json_decode(Cache::getAuthInfo("corpAuthInfo_".$corpId));
+ $agents = $authInfo->agent;
+ $agentId = 0;
+ foreach($agents as $agent){
+ if($agent->appid==$appId){
+ $agentId = $agent->agentid;
+ break;
+ }
+ }
+ Log::i("[AGENTID]".$corpId."-----".$appId."-----".$agentId);
+ return $agentId;
+ }
+
+ public static function getIsvCorpAccessToken($suiteAccessToken, $authCorpId, $permanentCode)
+ {
+ $key = "IsvCorpAccessToken_".$authCorpId;
+ $corpAccessToken = Cache::getIsvCorpAccessToken($key);
+ if (!$corpAccessToken)
+ {
+ $response = Http::post("/service/get_corp_token",
+ array(
+ "suite_access_token" => $suiteAccessToken
+ ),
+ json_encode(array(
+ "auth_corpid" => $authCorpId,
+ "permanent_code" => $permanentCode
+ )));
+ self::check($response);
+ $corpAccessToken = $response->access_token;
+ Cache::setIsvCorpAccessToken($key,$corpAccessToken);
+ }
+ return $corpAccessToken;
+ }
+
+ public static function getAuthInfo($suiteAccessToken, $authCorpId, $permanentCode)
+ {
+ $authInfo = json_decode(Cache::getAuthInfo("corpAuthInfo_".$authCorpId));
+ if (!$authInfo)
+ {
+ $authInfo = Http::post("/service/get_auth_info",
+ array(
+ "suite_access_token" => $suiteAccessToken
+ ),
+ json_encode(array(
+ "suite_key" => SUITE_KEY,
+ "auth_corpid" => $authCorpId,
+ "permanent_code" => $permanentCode
+ )));
+ self::check($authInfo);
+ Cache::setAuthInfo("corpAuthInfo_".$authCorpId,json_encode($authInfo->auth_info));
+ }
+
+ return $authInfo;
+ }
+
+
+ public static function getAgent($suiteAccessToken, $authCorpId, $permanentCode, $agentId)
+ {
+ $response = Http::post("/service/get_agent",
+ array(
+ "suite_access_token" => $suiteAccessToken
+ ),
+ json_encode(array(
+ "suite_key" => SUITE_KEY,
+ "auth_corpid" => $authCorpId,
+ "permanent_code" => $permanentCode,
+ "agentid" => $agentId
+ )));
+ self::check($response);
+ return $response;
+ }
+
+
+ public static function activeSuite($suiteAccessToken, $authCorpId, $permanentCode)
+ {
+ $key = "dingdingActive_".$authCorpId;
+ $response = Http::post("/service/activate_suite",
+ array(
+ "suite_access_token" => $suiteAccessToken
+ ),
+ json_encode(array(
+ "suite_key" => SUITE_KEY,
+ "auth_corpid" => $authCorpId,
+ "permanent_code" => $permanentCode
+ )));
+
+ if($response->errcode==0){
+ Cache::setActiveStatus($key);
+ }
+ self::check($response);
+ return $response;
+ }
+
+ public static function removeCorpInfo($authCorpId){
+ $arr = array();
+ $key1 = "dingdingActive_".$authCorpId;
+ $key2 = "corpAuthInfo_".$authCorpId;
+ $key3 = "IsvCorpAccessToken_".$authCorpId;
+ $key4 = "js_ticket_".$authCorpId;
+ $arr[] = $key1;
+ $arr[] = $key2;
+ $arr[] = $key3;
+ $arr[] = $key4;
+ Cache::removeByKeyArr($arr);
+ }
+
+ static function check($res)
+ {
+ if ($res->errcode != 0)
+ {
+ Log::e("[FAIL]: " . json_encode($res));
+ exit("Failed: " . json_encode($res));
+ }
+ }
+}
diff --git a/dingdingcallback/api/Message.php b/dingdingcallback/api/Message.php
new file mode 100644
index 00000000..43c5dcb2
--- /dev/null
+++ b/dingdingcallback/api/Message.php
@@ -0,0 +1,18 @@
+ $accessToken),
+ json_encode($opt));
+ return $response;
+ }
+
+ public static function send($accessToken, $opt)
+ {
+ $response = Http::post("/message/send",
+ array("access_token" => $accessToken),json_encode($opt));
+ return $response;
+ }
+}
\ No newline at end of file
diff --git a/dingdingcallback/api/User.php b/dingdingcallback/api/User.php
new file mode 100644
index 00000000..0031e114
--- /dev/null
+++ b/dingdingcallback/api/User.php
@@ -0,0 +1,18 @@
+ $accessToken, "code" => $code));
+ return json_encode($response);
+ }
+
+
+ public static function simplelist($accessToken,$deptId){
+ $response = Http::get("/user/simplelist",
+ array("access_token" => $accessToken,"department_id"=>$deptId));
+ return $response->userlist;
+
+ }
+}
diff --git a/dingdingcallback/composer.json b/dingdingcallback/composer.json
new file mode 100644
index 00000000..c5e87a60
--- /dev/null
+++ b/dingdingcallback/composer.json
@@ -0,0 +1,5 @@
+{
+ "require": {
+ "nategood/httpful": "*"
+ }
+}
diff --git a/dingdingcallback/composer.lock b/dingdingcallback/composer.lock
new file mode 100644
index 00000000..f65516a8
--- /dev/null
+++ b/dingdingcallback/composer.lock
@@ -0,0 +1,68 @@
+{
+ "_readme": [
+ "This file locks the dependencies of your project to a known state",
+ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
+ "This file is @generated automatically"
+ ],
+ "hash": "e23d30d76ba6b3d3bcdab145c9f7f9f3",
+ "packages": [
+ {
+ "name": "nategood/httpful",
+ "version": "0.2.19",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nategood/httpful.git",
+ "reference": "bd73f89d34d8f879c54ac46eb94b0f7be1d00820"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nategood/httpful/zipball/bd73f89d34d8f879c54ac46eb94b0f7be1d00820",
+ "reference": "bd73f89d34d8f879c54ac46eb94b0f7be1d00820",
+ "shasum": ""
+ },
+ "require": {
+ "ext-curl": "*",
+ "php": ">=5.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "*"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-0": {
+ "Httpful": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nate Good",
+ "email": "me@nategood.com",
+ "homepage": "http://nategood.com"
+ }
+ ],
+ "description": "A Readable, Chainable, REST friendly, PHP HTTP Client",
+ "homepage": "http://github.com/nategood/httpful",
+ "keywords": [
+ "api",
+ "curl",
+ "http",
+ "requests",
+ "rest",
+ "restful"
+ ],
+ "time": "2015-03-08 15:22:23"
+ }
+ ],
+ "packages-dev": [],
+ "aliases": [],
+ "minimum-stability": "stable",
+ "stability-flags": [],
+ "prefer-stable": false,
+ "prefer-lowest": false,
+ "platform": [],
+ "platform-dev": []
+}
diff --git a/dingdingcallback/config.php b/dingdingcallback/config.php
new file mode 100644
index 00000000..cb6af7aa
--- /dev/null
+++ b/dingdingcallback/config.php
@@ -0,0 +1,11 @@
+m_token = $token;
+ $this->m_encodingAesKey = $encodingAesKey;
+ $this->m_suiteKey = $suiteKey;
+ }
+
+
+ public function EncryptMsg($plain, $timeStamp, $nonce, &$encryptMsg)
+ {
+ $pc = new Prpcrypt($this->m_encodingAesKey);
+
+ $array = $pc->encrypt($plain, $this->m_suiteKey);
+ $ret = $array[0];
+ if ($ret != 0) {
+ return $ret;
+ }
+
+ if ($timeStamp == null) {
+ $timeStamp = time();
+ }
+ $encrypt = $array[1];
+
+ $sha1 = new SHA1;
+ $array = $sha1->getSHA1($this->m_token, $timeStamp, $nonce, $encrypt);
+ $ret = $array[0];
+ if ($ret != 0) {
+ return $ret;
+ }
+ $signature = $array[1];
+
+ $encryptMsg = json_encode(array(
+ "msg_signature" => $signature,
+ "encrypt" => $encrypt,
+ "timeStamp" => $timeStamp,
+ "nonce" => $nonce
+ ));
+ return ErrorCode::$OK;
+ }
+
+
+ public function DecryptMsg($signature, $timeStamp = null, $nonce, $encrypt, &$decryptMsg)
+ {
+ if (strlen($this->m_encodingAesKey) != 43) {
+ return ErrorCode::$IllegalAesKey;
+ }
+
+ $pc = new Prpcrypt($this->m_encodingAesKey);
+
+ if ($timeStamp == null) {
+ $timeStamp = time();
+ }
+
+ $sha1 = new SHA1;
+ $array = $sha1->getSHA1($this->m_token, $timeStamp, $nonce, $encrypt);
+ $ret = $array[0];
+
+ if ($ret != 0) {
+ return $ret;
+ }
+
+ $verifySignature = $array[1];
+ if ($verifySignature != $signature) {
+ return ErrorCode::$ValidateSignatureError;
+ }
+
+ $result = $pc->decrypt($encrypt, $this->m_suiteKey);
+ if ($result[0] != 0) {
+ return $result[0];
+ }
+ $decryptMsg = $result[1];
+
+ return ErrorCode::$OK;
+ }
+
+}
+
diff --git a/dingdingcallback/crypto/errorCode.php b/dingdingcallback/crypto/errorCode.php
new file mode 100644
index 00000000..c5edf8da
--- /dev/null
+++ b/dingdingcallback/crypto/errorCode.php
@@ -0,0 +1,26 @@
+
+ *
-900004: encodingAesKey 非法
+ * -900005: 签名验证错误
+ * -900006: sha加密生成签名失败
+ * -900007: aes 加密失败
+ * -900008: aes 解密失败
+ * -900010: suiteKey 校验错误
+ *
+ */
+class ErrorCode
+{
+ public static $OK = 0;
+
+ public static $IllegalAesKey = 900004;
+ public static $ValidateSignatureError = 900005;
+ public static $ComputeSignatureError = 900006;
+ public static $EncryptAESError = 900007;
+ public static $DecryptAESError = 900008;
+ public static $ValidateSuiteKeyError = 900010;
+}
+
+?>
\ No newline at end of file
diff --git a/dingdingcallback/crypto/pkcs7Encoder.php b/dingdingcallback/crypto/pkcs7Encoder.php
new file mode 100644
index 00000000..2b6948cd
--- /dev/null
+++ b/dingdingcallback/crypto/pkcs7Encoder.php
@@ -0,0 +1,129 @@
+ PKCS7Encoder::$block_size) {
+ $pad = 0;
+ }
+ return substr($text, 0, (strlen($text) - $pad));
+ }
+
+}
+
+
+class Prpcrypt
+{
+ public $key;
+
+ function Prpcrypt($k)
+ {
+ $this->key = base64_decode($k . "=");
+ }
+
+ public function encrypt($text, $corpid)
+ {
+
+ try {
+ //获得16位随机字符串,填充到明文之前
+ $random = $this->getRandomStr();
+ $text = $random . pack("N", strlen($text)) . $text . $corpid;
+ // 网络字节序
+ $size = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
+ $module = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
+ $iv = substr($this->key, 0, 16);
+ //使用自定义的填充方式对明文进行补位填充
+ $pkc_encoder = new PKCS7Encoder;
+ $text = $pkc_encoder->encode($text);
+ mcrypt_generic_init($module, $this->key, $iv);
+ //加密
+ $encrypted = mcrypt_generic($module, $text);
+ mcrypt_generic_deinit($module);
+ mcrypt_module_close($module);
+
+ //print(base64_encode($encrypted));
+ //使用BASE64对加密后的字符串进行编码
+ return array(ErrorCode::$OK, base64_encode($encrypted));
+ } catch (Exception $e) {
+ print $e;
+ return array(ErrorCode::$EncryptAESError, null);
+ }
+ }
+
+ public function decrypt($encrypted, $corpid)
+ {
+
+ try {
+ $ciphertext_dec = base64_decode($encrypted);
+ $module = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
+ $iv = substr($this->key, 0, 16);
+ mcrypt_generic_init($module, $this->key, $iv);
+
+ $decrypted = mdecrypt_generic($module, $ciphertext_dec);
+ mcrypt_generic_deinit($module);
+ mcrypt_module_close($module);
+ } catch (Exception $e) {
+ return array(ErrorCode::$DecryptAESError, null);
+ }
+
+
+ try {
+ //去除补位字符
+ $pkc_encoder = new PKCS7Encoder;
+ $result = $pkc_encoder->decode($decrypted);
+ //去除16位随机字符串,网络字节序和AppId
+ if (strlen($result) < 16)
+ return "";
+ $content = substr($result, 16, strlen($result));
+ $len_list = unpack("N", substr($content, 0, 4));
+ $xml_len = $len_list[1];
+ $xml_content = substr($content, 4, $xml_len);
+ $from_corpid = substr($content, $xml_len + 4);
+ } catch (Exception $e) {
+ print $e;
+ return array(ErrorCode::$DecryptAESError, null);
+ }
+ if ($from_corpid != $corpid)
+ return array(ErrorCode::$ValidateSuiteKeyError, null);
+ return array(0, $xml_content);
+
+ }
+
+ function getRandomStr()
+ {
+
+ $str = "";
+ $str_pol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
+ $max = strlen($str_pol) - 1;
+ for ($i = 0; $i < 16; $i++) {
+ $str .= $str_pol[mt_rand(0, $max)];
+ }
+ return $str;
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/dingdingcallback/crypto/sha1.php b/dingdingcallback/crypto/sha1.php
new file mode 100644
index 00000000..400d4ffb
--- /dev/null
+++ b/dingdingcallback/crypto/sha1.php
@@ -0,0 +1,23 @@
+
\ No newline at end of file
diff --git a/dingdingcallback/filecache.php b/dingdingcallback/filecache.php
new file mode 100644
index 00000000..4d66f3ff
--- /dev/null
+++ b/dingdingcallback/filecache.php
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/dingdingcallback/getPerson.php b/dingdingcallback/getPerson.php
new file mode 100644
index 00000000..8b2a0170
--- /dev/null
+++ b/dingdingcallback/getPerson.php
@@ -0,0 +1,16 @@
+
+
+
+
+ jsapi demo
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dingdingcallback/indexpc.php b/dingdingcallback/indexpc.php
new file mode 100644
index 00000000..ac37e5a9
--- /dev/null
+++ b/dingdingcallback/indexpc.php
@@ -0,0 +1,22 @@
+
+
+
+
+ jsapi demo
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dingdingcallback/isv.log b/dingdingcallback/isv.log
new file mode 100644
index 00000000..c7252675
--- /dev/null
+++ b/dingdingcallback/isv.log
@@ -0,0 +1,60 @@
+E/ 2020-01-08 09:57:27 ERROR: suiteTicket not cached,please check the callback url
+E/ 2020-01-08 09:57:32 [FAIL]: {"errcode":40014,"errmsg":"\u4e0d\u5408\u6cd5\u7684access_token"}
+E/ 2020-01-08 09:57:57 [] ERR:900004
+E/ 2020-01-08 09:57:57 []CREATE SUITE ERR:900004
+E/ 2020-01-08 09:59:01 [] ERR:900004
+E/ 2020-01-08 09:59:01 []CREATE SUITE ERR:900004
+E/ 2020-01-08 09:59:06 [] ERR:900004
+E/ 2020-01-08 09:59:06 []CREATE SUITE ERR:900004
+E/ 2020-01-08 10:00:15 [] ERR:900004
+E/ 2020-01-08 10:00:15 []CREATE SUITE ERR:900004
+E/ 2020-01-08 10:46:10 [] ERR:900004
+E/ 2020-01-08 10:46:10 []CREATE SUITE ERR:900004
+E/ 2020-01-08 10:46:33 [] ERR:900004
+E/ 2020-01-08 10:46:33 []CREATE SUITE ERR:900004
+E/ 2020-01-08 10:46:35 [] ERR:900004
+E/ 2020-01-08 10:46:35 []CREATE SUITE ERR:900004
+E/ 2020-01-08 10:47:08 [] ERR:900004
+E/ 2020-01-08 10:47:08 []CREATE SUITE ERR:900004
+E/ 2020-01-08 10:47:09 [] ERR:900004
+E/ 2020-01-08 10:47:09 []CREATE SUITE ERR:900004
+E/ 2020-01-08 10:47:55 [] ERR:900004
+E/ 2020-01-08 10:47:55 []CREATE SUITE ERR:900004
+E/ 2020-01-08 10:47:57 [] ERR:900004
+E/ 2020-01-08 10:47:57 []CREATE SUITE ERR:900004
+E/ 2020-01-08 10:48:29 [] ERR:900004
+E/ 2020-01-08 10:48:29 []CREATE SUITE ERR:900004
+E/ 2020-01-08 10:48:30 [] ERR:900004
+E/ 2020-01-08 10:48:30 []CREATE SUITE ERR:900004
+E/ 2020-01-08 10:48:30 [] ERR:900004
+E/ 2020-01-08 10:48:30 []CREATE SUITE ERR:900004
+E/ 2020-01-08 10:48:31 [] ERR:900004
+E/ 2020-01-08 10:48:31 []CREATE SUITE ERR:900004
+E/ 2020-01-08 10:48:31 [] ERR:900004
+E/ 2020-01-08 10:48:31 []CREATE SUITE ERR:900004
+E/ 2020-01-08 02:44:14 [] ERR:900004
+E/ 2020-01-08 02:44:14 []CREATE SUITE ERR:900004
+E/ 2020-01-08 02:48:15 [] ERR:900005
+E/ 2020-01-08 02:48:15 []CREATE SUITE ERR:900005
+E/ 2020-01-08 02:48:38 [] ERR:900005
+E/ 2020-01-08 02:48:38 []CREATE SUITE ERR:900005
+E/ 2020-01-08 02:49:13 [] ERR:900005
+E/ 2020-01-08 02:49:13 []CREATE SUITE ERR:900005
+E/ 2020-01-08 02:49:34 [] ERR:900005
+E/ 2020-01-08 02:49:34 []CREATE SUITE ERR:900005
+E/ 2020-01-08 02:50:35 [] ERR:900005
+E/ 2020-01-08 02:50:35 []CREATE SUITE ERR:900005
+E/ 2020-01-08 02:50:36 [] ERR:900005
+E/ 2020-01-08 02:50:36 []CREATE SUITE ERR:900005
+E/ 2020-01-08 02:50:36 [] ERR:900005
+E/ 2020-01-08 02:50:36 []CREATE SUITE ERR:900005
+E/ 2020-01-08 02:50:36 [] ERR:900005
+E/ 2020-01-08 02:50:36 []CREATE SUITE ERR:900005
+I/ 2020-01-08 04:17:37 DECRYPT MSG SUCCESS [] {"EventType":"check_url"}
+I/ 2020-01-08 04:17:37 RESPONSE: {"msg_signature":"dddd562596877498f925cfde6be89dcdb2b0b260","encrypt":"bfWI8rpT2xLmwK78PjZOy7yv4UptXvYMPPNaZdeUtPrJBV15bBCJB\/X8RNzU9nybvfgt2fP5WJ6wKE\/5cjNeew==","timeStamp":"1578453834041","nonce":"bpmnoUjO"}
+E/ 2020-01-08 04:45:11 ERROR: suiteTicket not cached,please check the callback url
+E/ 2020-01-08 04:45:12 [FAIL]: {"errcode":40014,"errmsg":"\u4e0d\u5408\u6cd5\u7684access_token"}
+I/ 2020-01-08 04:45:24 DECRYPT MSG SUCCESS [] {"EventType":"check_url"}
+I/ 2020-01-08 04:45:24 RESPONSE: {"msg_signature":"9b012263e14a86181c1b1440cf3b9d24d10fb94f","encrypt":"WCP4qSubCQ4zqzuLvc5rWvOEsoISdZf44MfTeJudHwS\/OdHbgthABNmWHOmWHXm8jvIz+9MHLX+jJzB3osGCbw==","timeStamp":"1578453834041","nonce":"bpmnoUjO"}
+E/ 2020-01-08 04:46:48 [] ERR:900005
+E/ 2020-01-08 04:46:48 []CREATE SUITE ERR:900005
diff --git a/dingdingcallback/public/javascripts/demo.js b/dingdingcallback/public/javascripts/demo.js
new file mode 100644
index 00000000..3f79b510
--- /dev/null
+++ b/dingdingcallback/public/javascripts/demo.js
@@ -0,0 +1,169 @@
+/**
+ * Created by liqiao on 8/10/15.
+ */
+
+logger.i('Here we go...');
+
+logger.i(location.href);
+
+/**
+ * _config comes from server-side template. see views/index.jade
+ */
+dd.config({
+ agentId: _config.agentId,
+ corpId: _config.corpId,
+ timeStamp: _config.timeStamp,
+ nonceStr: _config.nonceStr,
+ signature: _config.signature,
+ jsApiList: [
+ 'runtime.info',
+ 'device.notification.prompt',
+ 'biz.chat.pickConversation',
+ 'device.notification.confirm',
+ 'device.notification.alert',
+ 'device.notification.prompt',
+ 'biz.chat.open',
+ 'biz.util.open',
+ 'biz.user.get',
+ 'biz.contact.choose',
+ 'biz.telephone.call',
+ 'biz.util.uploadImage',
+ 'biz.ding.post']
+});
+dd.userid=0;
+dd.ready(function() {
+ logger.i('dd.ready rocks!');
+
+ dd.runtime.info({
+ onSuccess: function(info) {
+ logger.i('runtime info: ' + JSON.stringify(info));
+ },
+ onFail: function(err) {
+ logger.e('fail: ' + JSON.stringify(err));
+ }
+ });
+
+ dd.runtime.permission.requestAuthCode({
+ corpId: _config.corpId, //企业id
+ onSuccess: function (info) {
+ logger.i('authcode: ' + info.code);
+ $.ajax({
+ url: '/sendMsg.php',
+ type:"POST",
+ data: {"event":"get_userinfo","code":info.code,"corpId":_config.corpId},
+ dataType:'json',
+ timeout: 900,
+ success: function (data, status, xhr) {
+ var info = JSON.parse(data);
+ if (info.errcode === 0) {
+ logger.i('user id: ' + info.userid);
+ dd.userid = info.userid;
+ }
+ else {
+ logger.e('auth error: ' + data);
+ }
+ },
+ error: function (xhr, errorType, error) {
+ logger.e(errorType + ', ' + error);
+ }
+ });
+ },
+ onFail: function (err) {
+ logger.e('requestAuthCode fail: ' + JSON.stringify(err));
+ }
+ });
+
+ $('.chooseonebtn').on('click', function() {
+
+ dd.biz.chat.pickConversation({
+ corpId: _config.corpId, //企业id
+ isConfirm:'false', //是否弹出确认窗口,默认为true
+ onSuccess: function (data) {
+ var chatinfo = data;
+ if(chatinfo){
+ console.log(chatinfo.cid);
+ dd.device.notification.prompt({
+ message: "发送消息",
+ title: chatinfo.title,
+ buttonLabels: ['发送', '取消'],
+ onSuccess : function(result) {
+ var text = result.value;
+ if(text==''){
+ return false;
+ }
+
+ $.ajax({
+ url: '/sendMsg.php',
+ type:"POST",
+ data: {"event":"send_to_conversation","cid":chatinfo.cid,"sender":dd.userid,"content":text,"corpId":_config.corpId},
+ dataType:'json',
+ timeout: 900,
+ success: function (data, status, xhr) {
+ var info = data;
+ logger.i('sendMsg: ' + JSON.stringify(data));
+ if(info.errcode==0){
+ logger.i('sendMsg: 发送成功');
+ /**
+ * 跳转到对话界面
+ */
+ dd.biz.chat.open({
+ cid:chatinfo.cid,
+ onSuccess : function(result) {
+ },
+ onFail : function(err) {}
+ });
+ }else{
+ logger.e('sendMsg: 发送失败'+info.errmsg);
+ }
+ },
+ error: function (xhr, errorType, error) {
+ logger.e(errorType + ', ' + error);
+ }
+ });
+ },
+ onFail : function(err) {}
+ });
+ }
+ },
+ onFail: function (err) {
+ }
+ });
+ });
+
+ $('.phonecall').on('click', function() {
+ dd.biz.contact.choose({
+ startWithDepartmentId: 0, //-1表示打开的通讯录从自己所在部门开始展示, 0表示从企业最上层开始,(其他数字表示从该部门开始:暂时不支持)
+ multiple: false, //是否多选: true多选 false单选; 默认true
+ users: [], //默认选中的用户列表,userid;成功回调中应包含该信息
+ corpId: _config.corpId, //企业id
+ max: 10, //人数限制,当multiple为true才生效,可选范围1-1500
+ onSuccess: function(data) {
+ if(data&&data.length>0){
+ var selectUserId = data[0].emplId;
+ if(selectUserId>0){
+ dd.biz.telephone.call({
+ users: [selectUserId], //用户列表,工号
+ corpId: _config.corpId, //企业id
+ onSuccess : function(info) {
+ logger.i('biz.telephone.call: info' + JSON.stringify(info));
+
+ },
+ onFail : function(err) {
+ logger.e('biz.telephone.call: error' + JSON.stringify(err));
+ }
+ })
+ }else{
+ return false;
+ }
+ }else{
+ return false;
+ }
+ },
+ onFail : function(err) {}
+ });
+ });
+});
+
+dd.error(function(err) {
+ logger.e('dd error: ' + JSON.stringify(err));
+});
diff --git a/dingdingcallback/public/javascripts/demopc.js b/dingdingcallback/public/javascripts/demopc.js
new file mode 100644
index 00000000..04bc0889
--- /dev/null
+++ b/dingdingcallback/public/javascripts/demopc.js
@@ -0,0 +1,135 @@
+/**
+ * Created by liqiao on 8/10/15.
+ */
+
+logger.i('Here we go...');
+
+logger.i(location.href);
+
+/**
+ * _config comes from server-side template. see views/index.jade
+ */
+DingTalkPC.config({
+ agentId: _config.agentId,
+ corpId: _config.corpId,
+ timeStamp: _config.timeStamp,
+ nonceStr: _config.nonceStr,
+ signature: _config.signature,
+ jsApiList: [
+ 'runtime.permission.requestAuthCode',
+ 'device.notification.alert',
+ 'device.notification.confirm',
+ 'biz.contact.choose',
+ 'device.notification.prompt',
+ 'biz.ding.post'
+ ] // 必填,需要使用的jsapi列表
+});
+DingTalkPC.userid=0;
+DingTalkPC.ready(function(res){
+ logger.i('dd.ready rocks!');
+
+ DingTalkPC.runtime.permission.requestAuthCode({
+ corpId: _config.corpId, //企业ID
+ onSuccess: function(info) {
+ logger.i('authcode: ' + info.code);
+ $.ajax({
+ url: '/sendMsg.php',
+ type:"POST",
+ data: {"event":"get_userinfo","code":info.code,"corpId":_config.corpId},
+ dataType:'json',
+ timeout: 900,
+ success: function (data, status, xhr) {
+ var info = JSON.parse(data);
+ if (info.errcode === 0) {
+ logger.i('user id: ' + info.userid);
+ DingTalkPC.userid = info.userid;
+ }
+ else {
+ logger.e('auth error: ' + data);
+ }
+ },
+ error: function (xhr, errorType, error) {
+ logger.e(errorType + ', ' + error);
+ }
+ });
+ },
+ onFail : function(err) {
+ logger.e(JSON.stringify(err));
+ }
+
+ });
+ $('.chooseonebtn').on('click', function() {
+
+ DingTalkPC.biz.contact.choose({
+ multiple: false, //是否多选: true多选 false单选; 默认true
+ users: [], //默认选中的用户列表,工号;成功回调中应包含该信息
+ corpId: _config.corpId, //企业id
+ max: 1, //人数限制,当multiple为true才生效,可选范围1-1500
+ onSuccess: function(data) {
+ if(data&&data.length>0){
+ var selectUserId = data[0].emplId;
+ if(selectUserId>0){
+ DingTalkPC.device.notification.prompt({
+ message: "发送消息",
+ title: data[0].name,
+ buttonLabels: ['发送', '取消'],
+ onSuccess : function(result) {
+ var textContent = result.value;
+ alert(textContent+">>>1");
+ if(textContent==''){
+ return false;
+ }
+ DingTalkPC.biz.ding.post({
+ users : [selectUserId],//用户列表,工号
+ corpId: _config.corpId, //加密的企业id
+ type: 1, //钉类型 1:image 2:link
+ alertType: 2,
+ alertDate: {"format":"yyyy-MM-dd HH:mm","value":"2016-05-09 08:00"},
+ attachment: {
+ images: [] //只取第一个image
+ }, //附件信息
+ text: textContent, //消息体
+ onSuccess : function(info) {
+ alert(">>>2");
+ logger.i('DingTalkPC.biz.ding.post: info' + JSON.stringify(info));
+ },
+ onFail : function(err) {
+ logger.e('DingTalkPC.biz.ding.post: info' + JSON.stringify(err));
+ }
+ })
+ /*
+ {
+ buttonIndex: 0, //被点击按钮的索引值,Number类型,从0开始
+ value: '' //输入的值
+ }
+ */
+ },
+ onFail : function(err) {
+ logger.e('DingTalkPC.biz.ding.post: info' + JSON.stringify(err));
+ }
+ });
+ }
+ }
+ },
+ onFail : function(err) {}
+ });
+ });
+ /*DingTalkPC.biz.util.uploadImage({
+ multiple: false, //是否多选,默认false
+ max: 5, //最多可选个数
+ onSuccess : function(result) {
+ logger.i(result);
+ },
+ onFail : function() {}
+ });*/
+ /*DingTalkPC.device.notification.alert({
+ message: "亲爱的",
+ title: "提示",//可传空
+ buttonName: "收到",
+ onSuccess : function() {
+ },
+ onFail : function(err) {}
+ });*/
+});
+
+
diff --git a/dingdingcallback/public/javascripts/logger.js b/dingdingcallback/public/javascripts/logger.js
new file mode 100644
index 00000000..5b015445
--- /dev/null
+++ b/dingdingcallback/public/javascripts/logger.js
@@ -0,0 +1,24 @@
+/**
+ * Created by liqiao on 8/14/15.
+ */
+
+var log = document.createElement('div');
+log.setAttribute('id', 'log');
+document.body.appendChild(log);
+
+var logger = {
+ i: function(info) {
+ add(info, 'i');
+ },
+ e: function(err) {
+ add(err, 'e');
+ }
+};
+
+function add(msg, level) {
+ var row = document.createElement('div');
+ row.setAttribute('class', 'log-row log-' + level);
+ row.innerHTML = msg;
+
+ document.querySelector('#log').appendChild(row);
+}
\ No newline at end of file
diff --git a/dingdingcallback/public/javascripts/zepto.min.js b/dingdingcallback/public/javascripts/zepto.min.js
new file mode 100644
index 00000000..1c9203e3
--- /dev/null
+++ b/dingdingcallback/public/javascripts/zepto.min.js
@@ -0,0 +1 @@
+(function(a){String.prototype.trim===a&&(String.prototype.trim=function(){return this.replace(/^\s+/,"").replace(/\s+$/,"")}),Array.prototype.reduce===a&&(Array.prototype.reduce=function(b){if(this===void 0||this===null)throw new TypeError;var c=Object(this),d=c.length>>>0,e=0,f;if(typeof b!="function")throw new TypeError;if(d==0&&arguments.length==1)throw new TypeError;if(arguments.length>=2)f=arguments[1];else do{if(e in c){f=c[e++];break}if(++e>=d)throw new TypeError}while(!0);while(e0?[].concat.apply([],a):a}function H(a){return a.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function I(a){return a in i?i[a]:i[a]=new RegExp("(^|\\s)"+a+"(\\s|$)")}function J(a,b){return typeof b=="number"&&!k[H(a)]?b+"px":b}function K(a){var b,c;return h[a]||(b=g.createElement(a),g.body.appendChild(b),c=j(b,"").getPropertyValue("display"),b.parentNode.removeChild(b),c=="none"&&(c="block"),h[a]=c),h[a]}function L(b,d){return d===a?c(b):c(b).filter(d)}function M(a,b,c,d){return A(b)?b.call(a,c,d):b}function N(a,b,d){var e=a%2?b:b.parentNode;e?e.insertBefore(d,a?a==1?e.firstChild:a==2?b:null:b.nextSibling):c(d).remove()}function O(a,b){b(a);for(var c in a.childNodes)O(a.childNodes[c],b)}var a,b,c,d,e=[],f=e.slice,g=window.document,h={},i={},j=g.defaultView.getComputedStyle,k={"column-count":1,columns:1,"font-weight":1,"line-height":1,opacity:1,"z-index":1,zoom:1},l=/^\s*<(\w+|!)[^>]*>/,m=[1,3,8,9,11],n=["after","prepend","before","append"],o=g.createElement("table"),p=g.createElement("tr"),q={tr:g.createElement("tbody"),tbody:o,thead:o,tfoot:o,td:p,th:p,"*":g.createElement("div")},r=/complete|loaded|interactive/,s=/^\.([\w-]+)$/,t=/^#([\w-]+)$/,u=/^[\w-]+$/,v={}.toString,w={},x,y,z=g.createElement("div");return w.matches=function(a,b){if(!a||a.nodeType!==1)return!1;var c=a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.matchesSelector;if(c)return c.call(a,b);var d,e=a.parentNode,f=!e;return f&&(e=z).appendChild(a),d=~w.qsa(e,b).indexOf(a),f&&z.removeChild(a),d},x=function(a){return a.replace(/-+(.)?/g,function(a,b){return b?b.toUpperCase():""})},y=function(a){return a.filter(function(b,c){return a.indexOf(b)==c})},w.fragment=function(b,d){d===a&&(d=l.test(b)&&RegExp.$1),d in q||(d="*");var e=q[d];return e.innerHTML=""+b,c.each(f.call(e.childNodes),function(){e.removeChild(this)})},w.Z=function(a,b){return a=a||[],a.__proto__=arguments.callee.prototype,a.selector=b||"",a},w.isZ=function(a){return a instanceof w.Z},w.init=function(b,d){if(!b)return w.Z();if(A(b))return c(g).ready(b);if(w.isZ(b))return b;var e;if(D(b))e=F(b);else if(C(b))e=[c.extend({},b)],b=null;else if(m.indexOf(b.nodeType)>=0||b===window)e=[b],b=null;else if(l.test(b))e=w.fragment(b.trim(),RegExp.$1),b=null;else{if(d!==a)return c(d).find(b);e=w.qsa(g,b)}return w.Z(e,b)},c=function(a,b){return w.init(a,b)},c.extend=function(c){return f.call(arguments,1).forEach(function(d){for(b in d)d[b]!==a&&(c[b]=d[b])}),c},w.qsa=function(a,b){var c;return a===g&&t.test(b)?(c=a.getElementById(RegExp.$1))?[c]:e:a.nodeType!==1&&a.nodeType!==9?e:f.call(s.test(b)?a.getElementsByClassName(RegExp.$1):u.test(b)?a.getElementsByTagName(b):a.querySelectorAll(b))},c.isFunction=A,c.isObject=B,c.isArray=D,c.isPlainObject=C,c.inArray=function(a,b,c){return e.indexOf.call(b,a,c)},c.trim=function(a){return a.trim()},c.uuid=0,c.map=function(a,b){var c,d=[],e,f;if(E(a))for(e=0;e0&&w.matches(this[0],a)},not:function(b){var d=[];if(A(b)&&b.call!==a)this.each(function(a){b.call(this,a)||d.push(this)});else{var e=typeof b=="string"?this.filter(b):E(b)&&A(b.item)?f.call(b):c(b);this.forEach(function(a){e.indexOf(a)<0&&d.push(a)})}return c(d)},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){var a=this[0];return a&&!B(a)?a:c(a)},last:function(){var a=this[this.length-1];return a&&!B(a)?a:c(a)},find:function(a){var b;return this.length==1?b=w.qsa(this[0],a):b=this.map(function(){return w.qsa(this,a)}),c(b)},closest:function(a,b){var d=this[0];while(d&&!w.matches(d,a))d=d!==b&&d!==g&&d.parentNode;return c(d)},parents:function(a){var b=[],d=this;while(d.length>0)d=c.map(d,function(a){if((a=a.parentNode)&&a!==g&&b.indexOf(a)<0)return b.push(a),a});return L(b,a)},parent:function(a){return L(y(this.pluck("parentNode")),a)},children:function(a){return L(this.map(function(){return f.call(this.children)}),a)},siblings:function(a){return L(this.map(function(a,b){return f.call(b.parentNode.children).filter(function(a){return a!==b})}),a)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(a){return this.map(function(){return this[a]})},show:function(){return this.each(function(){this.style.display=="none"&&(this.style.display=null),j(this,"").getPropertyValue("display")=="none"&&(this.style.display=K(this.nodeName))})},replaceWith:function(a){return this.before(a).remove()},wrap:function(a){return this.each(function(){c(this).wrapAll(c(a)[0].cloneNode(!1))})},wrapAll:function(a){return this[0]&&(c(this[0]).before(a=c(a)),a.append(this)),this},unwrap:function(){return this.parent().each(function(){c(this).replaceWith(c(this).children())}),this},clone:function(){return c(this.map(function(){return this.cloneNode(!0)}))},hide:function(){return this.css("display","none")},toggle:function(b){return(b===a?this.css("display")=="none":b)?this.show():this.hide()},prev:function(){return c(this.pluck("previousElementSibling"))},next:function(){return c(this.pluck("nextElementSibling"))},html:function(b){return b===a?this.length>0?this[0].innerHTML:null:this.each(function(a){var d=this.innerHTML;c(this).empty().append(M(this,b,a,d))})},text:function(b){return b===a?this.length>0?this[0].textContent:null:this.each(function(){this.textContent=b})},attr:function(c,d){var e;return typeof c=="string"&&d===a?this.length==0||this[0].nodeType!==1?a:c=="value"&&this[0].nodeName=="INPUT"?this.val():!(e=this[0].getAttribute(c))&&c in this[0]?this[0][c]:e:this.each(function(a){if(this.nodeType!==1)return;if(B(c))for(b in c)this.setAttribute(b,c[b]);else this.setAttribute(c,M(this,d,a,this.getAttribute(c)))})},removeAttr:function(a){return this.each(function(){this.nodeType===1&&this.removeAttribute(a)})},prop:function(b,c){return c===a?this[0]?this[0][b]:a:this.each(function(a){this[b]=M(this,c,a,this[b])})},data:function(b,c){var d=this.attr("data-"+H(b),c);return d!==null?d:a},val:function(b){return b===a?this.length>0?this[0].value:a:this.each(function(a){this.value=M(this,b,a,this.value)})},offset:function(){if(this.length==0)return null;var a=this[0].getBoundingClientRect();return{left:a.left+window.pageXOffset,top:a.top+window.pageYOffset,width:a.width,height:a.height}},css:function(c,d){if(d===a&&typeof c=="string")return this.length==0?a:this[0].style[x(c)]||j(this[0],"").getPropertyValue(c);var e="";for(b in c)typeof c[b]=="string"&&c[b]==""?this.each(function(){this.style.removeProperty(H(b))}):e+=H(b)+":"+J(b,c[b])+";";return typeof c=="string"&&(d==""?this.each(function(){this.style.removeProperty(H(c))}):e=H(c)+":"+J(c,d)),this.each(function(){this.style.cssText+=";"+e})},index:function(a){return a?this.indexOf(c(a)[0]):this.parent().children().indexOf(this[0])},hasClass:function(a){return this.length<1?!1:I(a).test(this[0].className)},addClass:function(a){return this.each(function(b){d=[];var e=this.className,f=M(this,a,b,e);f.split(/\s+/g).forEach(function(a){c(this).hasClass(a)||d.push(a)},this),d.length&&(this.className+=(e?" ":"")+d.join(" "))})},removeClass:function(b){return this.each(function(c){if(b===a)return this.className="";d=this.className,M(this,b,c,d).split(/\s+/g).forEach(function(a){d=d.replace(I(a)," ")}),this.className=d.trim()})},toggleClass:function(b,d){return this.each(function(e){var f=M(this,b,e,this.className);(d===a?!c(this).hasClass(f):d)?c(this).addClass(f):c(this).removeClass(f)})}},["width","height"].forEach(function(b){c.fn[b]=function(d){var e,f=b.replace(/./,function(a){return a[0].toUpperCase()});return d===a?this[0]==window?window["inner"+f]:this[0]==g?g.documentElement["offset"+f]:(e=this.offset())&&e[b]:this.each(function(a){var e=c(this);e.css(b,M(this,d,a,e[b]()))})}}),n.forEach(function(a,b){c.fn[a]=function(){var a=c.map(arguments,function(a){return B(a)?a:w.fragment(a)});if(a.length<1)return this;var d=this.length,e=d>1,f=b<2;return this.each(function(c,g){for(var h=0;h0&&this.bind(o,n),setTimeout(function(){m.css(i),e<=0&&setTimeout(function(){m.each(function(){n.call(this)})},0)},0),this},i=null}(Zepto),function($){function triggerAndReturn(a,b,c){var d=$.Event(b);return $(a).trigger(d,c),!d.defaultPrevented}function triggerGlobal(a,b,c,d){if(a.global)return triggerAndReturn(b||document,c,d)}function ajaxStart(a){a.global&&$.active++===0&&triggerGlobal(a,null,"ajaxStart")}function ajaxStop(a){a.global&&!--$.active&&triggerGlobal(a,null,"ajaxStop")}function ajaxBeforeSend(a,b){var c=b.context;if(b.beforeSend.call(c,a,b)===!1||triggerGlobal(b,c,"ajaxBeforeSend",[a,b])===!1)return!1;triggerGlobal(b,c,"ajaxSend",[a,b])}function ajaxSuccess(a,b,c){var d=c.context,e="success";c.success.call(d,a,e,b),triggerGlobal(c,d,"ajaxSuccess",[b,c,a]),ajaxComplete(e,b,c)}function ajaxError(a,b,c,d){var e=d.context;d.error.call(e,c,b,a),triggerGlobal(d,e,"ajaxError",[c,d,a]),ajaxComplete(b,c,d)}function ajaxComplete(a,b,c){var d=c.context;c.complete.call(d,b,a),triggerGlobal(c,d,"ajaxComplete",[b,c]),ajaxStop(c)}function empty(){}function mimeToDataType(a){return a&&(a==htmlType?"html":a==jsonType?"json":scriptTypeRE.test(a)?"script":xmlTypeRE.test(a)&&"xml")||"text"}function appendQuery(a,b){return(a+"&"+b).replace(/[&?]{1,2}/,"?")}function serializeData(a){isObject(a.data)&&(a.data=$.param(a.data)),a.data&&(!a.type||a.type.toUpperCase()=="GET")&&(a.url=appendQuery(a.url,a.data))}function serialize(a,b,c,d){var e=$.isArray(b);$.each(b,function(b,f){d&&(b=c?d:d+"["+(e?"":b)+"]"),!d&&e?a.add(f.name,f.value):(c?$.isArray(f):isObject(f))?serialize(a,f,c,b):a.add(b,f)})}var jsonpID=0,isObject=$.isObject,document=window.document,key,name,rscript=/