colly
2017-07-29 79ad053ba719b8d33d4e6d96a6dd3fbe415f23b1
接口上传
47 files added
5 files modified
4797 ■■■■■ changed files
Config/app.php 12 ●●●●● patch | view | raw | blame | history
Library/Alidayu/Config/app.php 16 ●●●●● patch | view | raw | blame | history
Library/Alidayu/Lite.php 82 ●●●●● patch | view | raw | blame | history
Library/Alidayu/SDK/ApplicationVar.php 47 ●●●●● patch | view | raw | blame | history
Library/Alidayu/SDK/ClusterTopClient.php 199 ●●●●● patch | view | raw | blame | history
Library/Alidayu/SDK/HttpdnsGetRequest.php 23 ●●●●● patch | view | raw | blame | history
Library/Alidayu/SDK/RequestCheckUtil.php 107 ●●●●● patch | view | raw | blame | history
Library/Alidayu/SDK/ResultSet.php 21 ●●●●● patch | view | raw | blame | history
Library/Alidayu/SDK/SpiUtils.php 214 ●●●●● patch | view | raw | blame | history
Library/Alidayu/SDK/TopClient.php 375 ●●●●● patch | view | raw | blame | history
Library/Alidayu/SDK/TopLogger.php 43 ●●●●● patch | view | raw | blame | history
Library/Alidayu/SDK/domain/Area.php 35 ●●●●● patch | view | raw | blame | history
Library/Alidayu/SDK/domain/BizResult.php 30 ●●●●● patch | view | raw | blame | history
Library/Alidayu/SDK/domain/FcPartnerSmsDetailDto.php 50 ●●●●● patch | view | raw | blame | history
Library/Alidayu/SDK/domain/KfcSearchResult.php 29 ●●●●● patch | view | raw | blame | history
Library/Alidayu/SDK/domain/Result.php 30 ●●●●● patch | view | raw | blame | history
Library/Alidayu/SDK/domain/Subtask.php 25 ●●●●● patch | view | raw | blame | history
Library/Alidayu/SDK/domain/Task.php 52 ●●●●● patch | view | raw | blame | history
Library/Alidayu/SDK/request/AlibabaAliqinFcFlowChargeProvinceRequest.php 98 ●●●●● patch | view | raw | blame | history
Library/Alidayu/SDK/request/AlibabaAliqinFcFlowChargeRequest.php 98 ●●●●● patch | view | raw | blame | history
Library/Alidayu/SDK/request/AlibabaAliqinFcFlowGradeRequest.php 32 ●●●●● patch | view | raw | blame | history
Library/Alidayu/SDK/request/AlibabaAliqinFcFlowQueryRequest.php 47 ●●●●● patch | view | raw | blame | history
Library/Alidayu/SDK/request/AlibabaAliqinFcSmsNumQueryRequest.php 115 ●●●●● patch | view | raw | blame | history
Library/Alidayu/SDK/request/AlibabaAliqinFcSmsNumSendRequest.php 131 ●●●●● patch | view | raw | blame | history
Library/Alidayu/SDK/request/AlibabaAliqinFcTtsNumSinglecallRequest.php 114 ●●●●● patch | view | raw | blame | history
Library/Alidayu/SDK/request/AlibabaAliqinFcVoiceNumDoublecallRequest.php 131 ●●●●● patch | view | raw | blame | history
Library/Alidayu/SDK/request/AlibabaAliqinFcVoiceNumSinglecallRequest.php 98 ●●●●● patch | view | raw | blame | history
Library/Alidayu/SDK/request/AppipGetRequest.php 32 ●●●●● patch | view | raw | blame | history
Library/Alidayu/SDK/request/AreasGetRequest.php 48 ●●●●● patch | view | raw | blame | history
Library/Alidayu/SDK/request/HttpdnsGetRequest.php 32 ●●●●● patch | view | raw | blame | history
Library/Alidayu/SDK/request/KfcKeywordSearchRequest.php 85 ●●●●● patch | view | raw | blame | history
Library/Alidayu/SDK/request/TimeGetRequest.php 32 ●●●●● patch | view | raw | blame | history
Library/Alidayu/SDK/request/TopAuthTokenCreateRequest.php 64 ●●●●● patch | view | raw | blame | history
Library/Alidayu/SDK/request/TopAuthTokenRefreshRequest.php 48 ●●●●● patch | view | raw | blame | history
Library/Alidayu/SDK/request/TopIpoutGetRequest.php 32 ●●●●● patch | view | raw | blame | history
Library/Alidayu/SDK/request/TopSecretGetRequest.php 64 ●●●●● patch | view | raw | blame | history
Library/Alidayu/SDK/request/TopatsResultGetRequest.php 48 ●●●●● patch | view | raw | blame | history
Library/Alidayu/SDK/request/TopatsTaskDeleteRequest.php 48 ●●●●● patch | view | raw | blame | history
Library/SMS/Config/app.php 21 ●●●●● patch | view | raw | blame | history
Library/SMS/Demo.php 34 ●●●●● patch | view | raw | blame | history
Library/SMS/Lite.php 297 ●●●●● patch | view | raw | blame | history
Library/SMS/README.md 81 ●●●●● patch | view | raw | blame | history
Library/SMS/SDK/REST.php 1042 ●●●●● patch | view | raw | blame | history
PhalApi/PhalApi/Helper/api_desc_tpl.php 26 ●●●●● patch | view | raw | blame | history
Public/listAllApis.php 53 ●●●●● patch | view | raw | blame | history
Public/yfs/checkApiParams.php 34 ●●●●● patch | view | raw | blame | history
Public/yfs/listAllApis.php 53 ●●●●● patch | view | raw | blame | history
Yfs/Api/Send.php 61 ●●●●● patch | view | raw | blame | history
Yfs/Api/User.php 165 ●●●●● patch | view | raw | blame | history
Yfs/Domain/SmsCode.php 65 ●●●●● patch | view | raw | blame | history
Yfs/Domain/User.php 59 ●●●●● patch | view | raw | blame | history
Yfs/Model/SmsCode.php 19 ●●●●● patch | view | raw | blame | history
Config/app.php
@@ -24,4 +24,16 @@
    'service_whitelist' => array(
        'Default.Index',
    ),
    'alidayu' => array(
        //短信签名
        'sign_name' => '七星博士',
        //模版列表
        'templates' => array(
            'register' => 'SMS_71216225'
        ),
        'app_key' => '23531128',
        'secretkey' => 'b079269785183c5a7520da9b8047bb42'
    )
);
Library/Alidayu/Config/app.php
New file
@@ -0,0 +1,16 @@
<?php
/**
 * 短信配置
 */
return array(
    'alidayu' => array(
        //短信签名
        'sign_name' => '七星博士',
        //模版列表
        'templates' => array(
            'register' => '71245307'
        )
    )
);
Library/Alidayu/Lite.php
New file
@@ -0,0 +1,82 @@
<?php
/**
 * 阿里大于扩展
 */
class Alidayu_Lite{
    static $_instance;
    public $sign_name = '';
    public $templates = array();
    public $app_key = '';
    public $secretkey = '';
    public function __construct(){
        DI()->loader->addDirs('./Library/Alidayu/SDK');
        DI()->loader->addDirs('./Library/Alidayu/SDK/request');
        DI()->loader->addDirs('./Library/Alidayu/SDK/domain');
        $config = DI()->config->get('app.alidayu');
        $this->sign_name = $config['sign_name'];
        $this->templates = $config['templates'];
        $this->app_key = $config['app_key'];
        $this->secretkey = $config['secretkey'];
    }
     /**
     * 单例模式
     * @return [type] [description]
     */
    public static function getInstance(){
        if(!(self::$_instance instanceof self)){
            self::$_instance = new self();
        }
        return self::$_instance;
    }
    /**
     * 发送验证码
     * @param  [type] $phone         [description]
     * @param  [type] $data        [description]
     * @param  [type] $use_scene [description]
     * @return [type]                [description]
     */
    public function send($phone, $send_json_data, $use_scene){
        if(!empty($use_scene)){
            if(isset($this->templates[$use_scene])){
                return $this->_send($phone, $send_json_data, $this->templates[$use_scene]);
            }
            else{
                return false;
            }
        }
        else{
            return false;
        }
    }
    /**
     * 阿里大于执行发送操作
     * @param  [type] $phone          [description]
     * @param  [type] $send_json_data [description]
     * @param  [type] $template_id    [description]
     * @return [type]                 [description]
     */
    private function _send($phone, $send_json_data, $template_id){
        $topClient = new TopClient();
        $topClient->appkey = $this->app_key;
        $topClient->secretKey = $this->secretkey;
        $req = new AlibabaAliqinFcSmsNumSendRequest();
        $req->setExtend($phone);
        $req->setSmsType('normal');
        $req->setSmsFreeSignName($this->sign_name);
        $req->setSmsParam($send_json_data);
        $req->setRecNum($phone);
        $req->setSmsTemplateCode($template_id);
        $resp = $topClient->execute($req);
        return $resp;
    }
}
Library/Alidayu/SDK/ApplicationVar.php
New file
@@ -0,0 +1,47 @@
<?php
class ApplicationVar
{
    var $save_file;
    var $application  = null;
     var $app_data    = '';
     var $__writed    = false;
    function __construct()
     {
    $this->save_file = __DIR__.'/httpdns.conf' ;
         $this->application = array();
     }
     public function setValue($var_name,$var_value)
  {
           if (!is_string($var_name) || empty($var_name))
            return false;
           $this->application[$var_name] = $var_value;
  }
  public function write(){
      $this->app_data = @serialize($this->application);
      $this->__writeToFile();
  }
     public function getValue()
     {
         if (!is_file($this->save_file))
             $this->__writeToFile();
         return @unserialize(@file_get_contents($this->save_file));
     }
     function __writeToFile()
     {
          $fp = @fopen($this->save_file,"w");
      if(flock($fp , LOCK_EX | LOCK_NB)){
          @fwrite($fp,$this->app_data);
          flock($fp , LOCK_UN);
      }
      @fclose($fp);
     }
}
?>
Library/Alidayu/SDK/ClusterTopClient.php
New file
@@ -0,0 +1,199 @@
<?php
class ClusterTopClient extends TopClient {
    private static $dnsconfig;
    private static $syncDate = 0;
    private static $applicationVar ;
    private static $cfgDuration = 10;
    public function __construct($appkey = "",$secretKey = ""){
        ClusterTopClient::$applicationVar = new ApplicationVar;
        $this->appkey = $appkey;
        $this->secretKey = $secretKey ;
        $saveConfig = ClusterTopClient::$applicationVar->getValue();
        if($saveConfig){
            $tmpConfig = $saveConfig['dnsconfig'];
            ClusterTopClient::$dnsconfig = $this->object_to_array($tmpConfig);
            unset($tmpConfig);
            ClusterTopClient::$syncDate = $saveConfig['syncDate'];
            if(!ClusterTopClient::$syncDate)
                ClusterTopClient::$syncDate = 0;
        }
    }
    public function __destruct(){
        if(ClusterTopClient::$dnsconfig && ClusterTopClient::$syncDate){
            ClusterTopClient::$applicationVar->setValue("dnsconfig",ClusterTopClient::$dnsconfig);
            ClusterTopClient::$applicationVar->setValue("syncDate",ClusterTopClient::$syncDate);
            ClusterTopClient::$applicationVar->write();
        }
    }
    public function execute($request = null, $session = null,$bestUrl = null){
        $currentDate = date('U');
        $syncDuration = $this->getDnsConfigSyncDuration();
        $bestUrl = $this->getBestVipUrl($this->gatewayUrl,$request->getApiMethodName(),$session);
        if($currentDate - ClusterTopClient::$syncDate > $syncDuration * 60){
            $httpdns = new HttpdnsGetRequest;
            ClusterTopClient::$dnsconfig = json_decode(parent::execute($httpdns,null,$bestUrl)->result,true);
            $syncDate = date('U');
            ClusterTopClient::$syncDate = $syncDate ;
        }
        return parent::execute($request,$session,$bestUrl);
    }
    private function getDnsConfigSyncDuration(){
        if(ClusterTopClient::$cfgDuration){
            return ClusterTopClient::$cfgDuration;
        }
        if(!ClusterTopClient::$dnsconfig){
            return ClusterTopClient::$cfgDuration;
        }
        $config = json_encode(ClusterTopClient::$dnsconfig);
        if(!$config){
            return ClusterTopClient::$cfgDuration;
        }
        $config = ClusterTopClient::$dnsconfig['config'];
        $duration = $config['interval'];
        ClusterTopClient::$cfgDuration = $duration;
        return ClusterTopClient::$cfgDuration;
    }
    private function getBestVipUrl($url,$apiname = null,$session = null){
        $config = ClusterTopClient::$dnsconfig['config'];
        $degrade = $config['degrade'];
        if(strcmp($degrade,'true') == 0){
            return $url;
        }
        $currentEnv = $this->getEnvByApiName($apiname,$session);
        $vip = $this->getVipByEnv($url,$currentEnv);
        if($vip)
            return $vip;
        return $url;
    }
    private function getVipByEnv($comUrl,$currentEnv){
        $urlSchema = parse_url($comUrl);
        if(!$urlSchema)
            return null;
        if(!ClusterTopClient::$dnsconfig['env'])
            return null;
        if(!array_key_exists($currentEnv,ClusterTopClient::$dnsconfig['env']))
            return null;
        $hostList = ClusterTopClient::$dnsconfig['env'][$currentEnv];
        if(!$hostList)
            return null ;
        $vipList = null;
        foreach ($hostList as $key => $value) {
            if(strcmp($key,$urlSchema['host']) == 0 && strcmp($value['proto'],$urlSchema['scheme']) == 0){
                $vipList = $value;
                break;
            }
        }
        $vip = $this->getRandomWeightElement($vipList['vip']);
        if($vip){
            return $urlSchema['scheme']."://".$vip.$urlSchema['path'];
        }
        return null;
    }
    private function getEnvByApiName($apiName,$session=""){
        $apiCfgArray = ClusterTopClient::$dnsconfig['api'];
        if($apiCfgArray){
            if(array_key_exists($apiName,$apiCfgArray)){
                $apiCfg = $apiCfgArray[$apiName];
                if(array_key_exists('user',$apiCfg)){
                    $userFlag = $apiCfg['user'];
                    $flag = $this->getUserFlag($session);
                    if($userFlag && $flag ){
                        return $this->getEnvBySessionFlag($userFlag,$flag);
                    }else{
                        return $this->getRandomWeightElement($apiCfg['rule']);
                    }
                }
            }
        }
        return $this->getDeafultEnv();
    }
    private function getUserFlag($session){
        if($session && strlen($session) > 5){
            if($session[0] == '6' || $session[0] == '7'){
                return $session[strlen($session) -1];
            }else if($session[0] == '5' || $session[0] == '8'){
                return $session[5];
            }
        }
        return null;
    }
    private function getEnvBySessionFlag($targetConfig,$flag){
        if($flag){
            $userConf = ClusterTopClient::$dnsconfig['user'];
            $cfgArry = $userConf[$targetConfig];
            foreach ($cfgArry as $key => $value) {
                if(in_array($flag,$value))
                    return $key;
            }
        }else{
            return null;
        }
    }
    private function getRandomWeightElement($elements){
        $totalWeight = 0;
        if($elements){
            foreach ($elements as $ele) {
                $weight = $this->getElementWeight($ele);
                $r = $this->randomFloat() * ($weight + $totalWeight);
                if($r >= $totalWeight){
                    $selected = $ele;
                }
                $totalWeight += $weight;
            }
            if($selected){
                return $this->getElementValue($selected);
            }
        }
        return null;
    }
    private function getElementWeight($ele){
        $params = explode('|', $ele);
        return floatval($params[1]);
    }
    private function getElementValue($ele){
        $params = explode('|', $ele);
        return $params[0];
    }
    private function getDeafultEnv(){
        return ClusterTopClient::$dnsconfig['config']['def_env'];
    }
    private static function startsWith($haystack, $needle) {
        return $needle === "" || strpos($haystack, $needle) === 0;
    }
    private function object_to_array($obj)
    {
        $_arr= is_object($obj) ? get_object_vars($obj) : $obj;
        foreach($_arr as $key=> $val)
        {
            $val= (is_array($val) || is_object($val))? $this->object_to_array($val) : $val;
            $arr[$key] = $val;
        }
        return$arr;
    }
    private function randomFloat($min = 0, $max = 1) { return $min + mt_rand() / mt_getrandmax() * ($max - $min); }
}
?>
Library/Alidayu/SDK/HttpdnsGetRequest.php
New file
@@ -0,0 +1,23 @@
<?php
class HttpdnsGetRequest
{
    private $apiParas = array();
    public function getApiMethodName()
    {
        return "taobao.httpdns.get";
    }
    public function getApiParas()
    {
        return $this->apiParas;
    }
    public function check(){}
    public function putOtherTextParam($key, $value) {
        $this->apiParas[$key] = $value;
        $this->$key = $value;
    }
}
Library/Alidayu/SDK/RequestCheckUtil.php
New file
@@ -0,0 +1,107 @@
<?php
/**
 * APIÈë²Î¾²Ì¬¼ì²éÀà
 * ¿ÉÒÔ¶ÔAPIµÄ²ÎÊýÀàÐÍ¡¢³¤¶È¡¢×î´óÖµµÈ½øÐÐУÑé
 *
 **/
class RequestCheckUtil
{
    /**
     * Ð£Ñé×ֶΠfieldName µÄÖµ$value·Ç¿Õ
     *
     **/
    public static function checkNotNull($value,$fieldName) {
        if(self::checkEmpty($value)){
            throw new Exception("client-check-error:Missing Required Arguments: " .$fieldName , 40);
        }
    }
    /**
     * ¼ìÑé×Ö¶ÎfieldNameµÄÖµvalue µÄ³¤¶È
     *
     **/
    public static function checkMaxLength($value,$maxLength,$fieldName){
        if(!self::checkEmpty($value) && mb_strlen($value , "UTF-8") > $maxLength){
            throw new Exception("client-check-error:Invalid Arguments:the length of " .$fieldName . " can not be larger than " . $maxLength . "." , 41);
        }
    }
    /**
     * ¼ìÑé×Ö¶ÎfieldNameµÄÖµvalueµÄ×î´óÁÐ±í³¤¶È
     *
     **/
    public static function checkMaxListSize($value,$maxSize,$fieldName) {
        if(self::checkEmpty($value))
            return ;
        $list=preg_split("/,/",$value);
        if(count($list) > $maxSize){
                throw new Exception("client-check-error:Invalid Arguments:the listsize(the string split by \",\") of ". $fieldName . " must be less than " . $maxSize . " ." , 41);
        }
    }
    /**
     * ¼ìÑé×Ö¶ÎfieldNameµÄÖµvalue µÄ×î´óÖµ
     *
     **/
    public static function checkMaxValue($value,$maxValue,$fieldName){
        if(self::checkEmpty($value))
            return ;
        self::checkNumeric($value,$fieldName);
        if($value > $maxValue){
                throw new Exception("client-check-error:Invalid Arguments:the value of " . $fieldName . " can not be larger than " . $maxValue ." ." , 41);
        }
    }
    /**
     * ¼ìÑé×Ö¶ÎfieldNameµÄÖµvalue µÄ×îСֵ
     *
     **/
    public static function checkMinValue($value,$minValue,$fieldName) {
        if(self::checkEmpty($value))
            return ;
        self::checkNumeric($value,$fieldName);
        if($value < $minValue){
                throw new Exception("client-check-error:Invalid Arguments:the value of " . $fieldName . " can not be less than " . $minValue . " ." , 41);
        }
    }
    /**
     * ¼ìÑé×Ö¶ÎfieldNameµÄÖµvalueÊÇ·ñÊÇnumber
     *
     **/
    protected static function checkNumeric($value,$fieldName) {
        if(!is_numeric($value))
            throw new Exception("client-check-error:Invalid Arguments:the value of " . $fieldName . " is not number : " . $value . " ." , 41);
    }
    /**
     * Ð£Ñé$valueÊÇ·ñ·Ç¿Õ
     *  if not set ,return true;
     *    if is null , return true;
     *
     *
     **/
    public static function checkEmpty($value) {
        if(!isset($value))
            return true ;
        if($value === null )
            return true;
        if(is_array($value) && count($value) == 0)
            return true;
        if(is_string($value) &&trim($value) === "")
            return true;
        return false;
    }
}
?>
Library/Alidayu/SDK/ResultSet.php
New file
@@ -0,0 +1,21 @@
<?php
/**
 * 返回的默认类
 *
 * @author auto create
 * @since 1.0, 2015-01-20
 */
class ResultSet
{
    /**
     * 返回的错误码
     **/
    public $code;
    /**
     * 返回的错误信息
     **/
    public $msg;
}
Library/Alidayu/SDK/SpiUtils.php
New file
@@ -0,0 +1,214 @@
<?php
class SpiUtils{
    private static $top_sign_list = "HTTP_TOP_SIGN_LIST";
    private static $timestamp = "timestamp";
    private static $header_real_ip = array("X_Real_IP", "X_Forwarded_For", "Proxy_Client_IP",
                                            "WL_Proxy_Client_IP", "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR");
    /**
     * 校验SPI请求签名,适用于所有GET请求,及不包含文件参数的POST请求。
     *
     * @param request 请求对象
     * @param secret app对应的secret
     * @return true:校验通过;false:校验不通过
     */
    public static function checkSign4FormRequest($secret){
        return self::checkSign(null,null,$secret);
    }
    /**
     * 校验SPI请求签名,适用于请求体是xml/json等可用文本表示的POST请求。
     *
     * @param request 请求对象
     * @param body 请求体的文本内容
     * @param secret app对应的secret
     * @return true:校验通过;false:校验不通过
     */
    public static function checkSign4TextRequest($body,$secret){
        return self::checkSign(null,$body,$secret);
    }
    /**
     * 校验SPI请求签名,适用于带文件上传的POST请求。
     *
     * @param request 请求对象
     * @param form 除了文件参数以外的所有普通文本参数的map集合
     * @param secret app对应的secret
     * @return true:校验通过;false:校验不通过
     */
    public static function checkSign4FileRequest($form, $secret){
        return self::checkSign($form, null, $secret);
    }
    private static function checkSign($form, $body, $secret) {
        $params = array();
        // 1. 获取header参数
        $headerMap = self::getHeaderMap();
        foreach ($headerMap as $k => $v){
            $params[$k] = $v ;
        }
        // 2. 获取url参数
        $queryMap = self::getQueryMap();
        foreach ($queryMap as $k => $v){
            $params[$k] = $v ;
        }
        // 3. 获取form参数
        if ($form == null && $body == null) {
            $formMap = self::getFormMap();
            foreach ($formMap as $k => $v){
                $params[$k] = $v ;
            }
        } else if ($form != null) {
            foreach ($form as $k => $v){
                $params[$k] = $v ;
            }
        }
        if($body == null){
            $body = file_get_contents('php://input');
        }
        $remoteSign = $queryMap["sign"];
        $localSign = self::sign($params, $body, $secret);
        if (strcmp($remoteSign, $localSign) == 0) {
            return true;
        } else {
            $paramStr = self::getParamStrFromMap($params);
            self::logCommunicationError($remoteSign,$localSign,$paramStr,$body);
            return false;
        }
    }
    private static function getHeaderMap() {
        $headerMap = array();
        $signList = $_SERVER['HTTP_TOP_SIGN_LIST']; // 只获取参与签名的头部字段
        $signList = trim($signList);
        if (strlen($signList) > 0){
            $params = split(",", $signList);
            foreach ($_SERVER as $k => $v){
                if (substr($k, 0, 5) == 'HTTP_'){
                    foreach($params as $kk){
                        $upperkey = strtoupper($kk);
                        if(self::endWith($k,$upperkey)){
                            $headerMap[$kk] = $v;
                        }
                    }
                }
            }
        }
        return $headerMap;
    }
    private static function getQueryMap(){
        $queryStr = $_SERVER["QUERY_STRING"];
        $resultArray = array();
        foreach (explode('&', $queryStr) as $pair) {
            list($key, $value) = explode('=', $pair);
            if (strpos($key, '.') !== false) {
                list($subKey, $subVal) = explode('.', $key);
                if (preg_match('/(?P<name>\w+)\[(?P<index>\w+)\]/', $subKey, $matches)) {
                    $resultArray[$matches['name']][$matches['index']][$subVal] = $value;
                } else {
                    $resultArray[$subKey][$subVal] = urldecode($value);
                }
            } else {
                $resultArray[$key] = urldecode($value);
            }
        }
        return $resultArray;
    }
    private static function checkRemoteIp(){
        $remoteIp = $_SERVER["REMOTE_ADDR"];
        foreach ($header_real_ip as $k){
            $realIp = $_SERVER[$k];
            $realIp = trim($realIp);
            if(strlen($realIp) > 0 && strcasecmp("unknown",$realIp)){
                $remoteIp = $realIp;
                break;
            }
        }
        return self::startsWith($remoteIp,"140.205.144.") || $this->startsWith($remoteIp,"40.205.145.");
    }
    private static function getFormMap(){
        $resultArray = array();
        foreach($_POST as $key=>$v) {
            $resultArray[$k] = $v ;
        }
        return $resultArray ;
    }
    private static function startsWith($haystack, $needle) {
        return $needle === "" || strpos($haystack, $needle) === 0;
    }
    private static function endWith($haystack, $needle) {
        $length = strlen($needle);
        if($length == 0)
        {
            return true;
        }
        return (substr($haystack, -$length) === $needle);
     }
    private static function checkTimestamp(){
        $ts = $_POST['timestamp'];
        if($ts){
            $clientTimestamp = strtotime($ts);
            $current = $_SERVER['REQUEST_TIME'];
            return ($current - $clientTimestamp) <= 5*60*1000;
        }else{
            return false;
        }
    }
    private static function getParamStrFromMap($params){
        ksort($params);
        $stringToBeSigned = "";
        foreach ($params as $k => $v)
        {
            if(strcmp("sign", $k) != 0)
            {
                $stringToBeSigned .= "$k$v";
            }
        }
        unset($k, $v);
        return $stringToBeSigned;
    }
    private static function sign($params,$body,$secret){
        ksort($params);
        $stringToBeSigned = $secret;
        $stringToBeSigned .= self::getParamStrFromMap($params);
        if($body)
            $stringToBeSigned .= $body;
        $stringToBeSigned .= $secret;
        return strtoupper(md5($stringToBeSigned));
    }
    protected static function logCommunicationError($remoteSign, $localSign, $paramStr, $body)
    {
        $localIp = isset($_SERVER["SERVER_ADDR"]) ? $_SERVER["SERVER_ADDR"] : "CLI";
        $logger = new TopLogger;
        $logger->conf["log_file"] = rtrim(TOP_SDK_WORK_DIR, '\\/') . '/' . "logs/top_comm_err_". date("Y-m-d") . ".log";
        $logger->conf["separator"] = "^_^";
        $logData = array(
        "checkTopSign error" ,
        "remoteSign=".$remoteSign ,
        "localSign=".$localSign ,
        "paramStr=".$paramStr ,
        "body=".$body
        );
        $logger->log($logData);
    }
    private static function clear_blank($str, $glue='')
    {
        $replace = array(" ", "\r", "\n", "\t"); return str_replace($replace, $glue, $str);
    }
}
?>
Library/Alidayu/SDK/TopClient.php
New file
@@ -0,0 +1,375 @@
<?php
class TopClient
{
    public $appkey;
    public $secretKey;
    public $gatewayUrl = "http://gw.api.taobao.com/router/rest";
    public $format = "xml";
    public $connectTimeout;
    public $readTimeout;
    /** 是否打开入参check**/
    public $checkRequest = true;
    protected $signMethod = "md5";
    protected $apiVersion = "2.0";
    protected $sdkVersion = "top-sdk-php-20151012";
    public function __construct($appkey = "",$secretKey = ""){
        $this->appkey = $appkey;
        $this->secretKey = $secretKey ;
    }
    protected function generateSign($params)
    {
        ksort($params);
        $stringToBeSigned = $this->secretKey;
        foreach ($params as $k => $v)
        {
            if(is_string($v) && "@" != substr($v, 0, 1))
            {
                $stringToBeSigned .= "$k$v";
            }
        }
        unset($k, $v);
        $stringToBeSigned .= $this->secretKey;
        return strtoupper(md5($stringToBeSigned));
    }
    public function curl($url, $postFields = null)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_FAILONERROR, false);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        if ($this->readTimeout) {
            curl_setopt($ch, CURLOPT_TIMEOUT, $this->readTimeout);
        }
        if ($this->connectTimeout) {
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->connectTimeout);
        }
        curl_setopt ( $ch, CURLOPT_USERAGENT, "top-sdk-php" );
        //https 请求
        if(strlen($url) > 5 && strtolower(substr($url,0,5)) == "https" ) {
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        }
        if (is_array($postFields) && 0 < count($postFields))
        {
            $postBodyString = "";
            $postMultipart = false;
            foreach ($postFields as $k => $v)
            {
                if(!is_string($v))
                    continue ;
                if("@" != substr($v, 0, 1))//判断是不是文件上传
                {
                    $postBodyString .= "$k=" . urlencode($v) . "&";
                }
                else//文件上传用multipart/form-data,否则用www-form-urlencoded
                {
                    $postMultipart = true;
                    if(class_exists('\CURLFile')){
                        $postFields[$k] = new \CURLFile(substr($v, 1));
                    }
                }
            }
            unset($k, $v);
            curl_setopt($ch, CURLOPT_POST, true);
            if ($postMultipart)
            {
                if (class_exists('\CURLFile')) {
                    curl_setopt($ch, CURLOPT_SAFE_UPLOAD, true);
                } else {
                    if (defined('CURLOPT_SAFE_UPLOAD')) {
                        curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);
                    }
                }
                curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
            }
            else
            {
                $header = array("content-type: application/x-www-form-urlencoded; charset=UTF-8");
                curl_setopt($ch,CURLOPT_HTTPHEADER,$header);
                curl_setopt($ch, CURLOPT_POSTFIELDS, substr($postBodyString,0,-1));
            }
        }
        $reponse = curl_exec($ch);
        if (curl_errno($ch))
        {
            throw new Exception(curl_error($ch),0);
        }
        else
        {
            $httpStatusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            if (200 !== $httpStatusCode)
            {
                throw new Exception($reponse,$httpStatusCode);
            }
        }
        curl_close($ch);
        return $reponse;
    }
    public function curl_with_memory_file($url, $postFields = null, $fileFields = null)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_FAILONERROR, false);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        if ($this->readTimeout) {
            curl_setopt($ch, CURLOPT_TIMEOUT, $this->readTimeout);
        }
        if ($this->connectTimeout) {
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->connectTimeout);
        }
        curl_setopt ( $ch, CURLOPT_USERAGENT, "top-sdk-php" );
        //https 请求
        if(strlen($url) > 5 && strtolower(substr($url,0,5)) == "https" ) {
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        }
        //生成分隔符
        $delimiter = '-------------' . uniqid();
        //先将post的普通数据生成主体字符串
        $data = '';
        if($postFields != null){
            foreach ($postFields as $name => $content) {
                $data .= "--" . $delimiter . "\r\n";
                $data .= 'Content-Disposition: form-data; name="' . $name . '"';
                //multipart/form-data 不需要urlencode,参见 http:stackoverflow.com/questions/6603928/should-i-url-encode-post-data
                $data .= "\r\n\r\n" . $content . "\r\n";
            }
            unset($name,$content);
        }
        //将上传的文件生成主体字符串
        if($fileFields != null){
            foreach ($fileFields as $name => $file) {
                $data .= "--" . $delimiter . "\r\n";
                $data .= 'Content-Disposition: form-data; name="' . $name . '"; filename="' . $file['name'] . "\" \r\n";
                $data .= 'Content-Type: ' . $file['type'] . "\r\n\r\n";//多了个文档类型
                $data .= $file['content'] . "\r\n";
            }
            unset($name,$file);
        }
        //主体结束的分隔符
        $data .= "--" . $delimiter . "--";
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER , array(
            'Content-Type: multipart/form-data; boundary=' . $delimiter,
            'Content-Length: ' . strlen($data))
        );
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        $reponse = curl_exec($ch);
        unset($data);
        if (curl_errno($ch))
        {
            throw new Exception(curl_error($ch),0);
        }
        else
        {
            $httpStatusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            if (200 !== $httpStatusCode)
            {
                throw new Exception($reponse,$httpStatusCode);
            }
        }
        curl_close($ch);
        return $reponse;
    }
    protected function logCommunicationError($apiName, $requestUrl, $errorCode, $responseTxt)
    {
        $localIp = isset($_SERVER["SERVER_ADDR"]) ? $_SERVER["SERVER_ADDR"] : "CLI";
        $logger = new TopLogger;
        $logger->conf["log_file"] = rtrim(TOP_SDK_WORK_DIR, '\\/') . '/' . "logs/top_comm_err_" . $this->appkey . "_" . date("Y-m-d") . ".log";
        $logger->conf["separator"] = "^_^";
        $logData = array(
        date("Y-m-d H:i:s"),
        $apiName,
        $this->appkey,
        $localIp,
        PHP_OS,
        $this->sdkVersion,
        $requestUrl,
        $errorCode,
        str_replace("\n","",$responseTxt)
        );
        $logger->log($logData);
    }
    public function execute($request, $session = null,$bestUrl = null)
    {
        $result =  new ResultSet();
        if($this->checkRequest) {
            try {
                $request->check();
            } catch (Exception $e) {
                $result->code = $e->getCode();
                $result->msg = $e->getMessage();
                return $result;
            }
        }
        //组装系统参数
        $sysParams["app_key"] = $this->appkey;
        $sysParams["v"] = $this->apiVersion;
        $sysParams["format"] = $this->format;
        $sysParams["sign_method"] = $this->signMethod;
        $sysParams["method"] = $request->getApiMethodName();
        $sysParams["timestamp"] = date("Y-m-d H:i:s");
        if (null != $session)
        {
            $sysParams["session"] = $session;
        }
        $apiParams = array();
        //获取业务参数
        $apiParams = $request->getApiParas();
        //系统参数放入GET请求串
        if($bestUrl){
            $requestUrl = $bestUrl."?";
            $sysParams["partner_id"] = $this->getClusterTag();
        }else{
            $requestUrl = $this->gatewayUrl."?";
            $sysParams["partner_id"] = $this->sdkVersion;
        }
        //签名
        $sysParams["sign"] = $this->generateSign(array_merge($apiParams, $sysParams));
        foreach ($sysParams as $sysParamKey => $sysParamValue)
        {
            // if(strcmp($sysParamKey,"timestamp") != 0)
            $requestUrl .= "$sysParamKey=" . urlencode($sysParamValue) . "&";
        }
        $fileFields = array();
        foreach ($apiParams as $key => $value) {
            if(is_array($value) && array_key_exists('type',$value) && array_key_exists('content',$value) ){
                $value['name'] = $key;
                $fileFields[$key] = $value;
                unset($apiParams[$key]);
            }
        }
        // $requestUrl .= "timestamp=" . urlencode($sysParams["timestamp"]) . "&";
        $requestUrl = substr($requestUrl, 0, -1);
        //发起HTTP请求
        try
        {
            if(count($fileFields) > 0){
                $resp = $this->curl_with_memory_file($requestUrl, $apiParams, $fileFields);
            }else{
                $resp = $this->curl($requestUrl, $apiParams);
            }
        }
        catch (Exception $e)
        {
            $this->logCommunicationError($sysParams["method"],$requestUrl,"HTTP_ERROR_" . $e->getCode(),$e->getMessage());
            $result->code = $e->getCode();
            $result->msg = $e->getMessage();
            return $result;
        }
        unset($apiParams);
        unset($fileFields);
        //解析TOP返回结果
        $respWellFormed = false;
        if ("json" == $this->format)
        {
            $respObject = json_decode($resp);
            if (null !== $respObject)
            {
                $respWellFormed = true;
                foreach ($respObject as $propKey => $propValue)
                {
                    $respObject = $propValue;
                }
            }
        }
        else if("xml" == $this->format)
        {
            $respObject = @simplexml_load_string($resp);
            if (false !== $respObject)
            {
                $respWellFormed = true;
            }
        }
        //返回的HTTP文本不是标准JSON或者XML,记下错误日志
        if (false === $respWellFormed)
        {
            $this->logCommunicationError($sysParams["method"],$requestUrl,"HTTP_RESPONSE_NOT_WELL_FORMED",$resp);
            $result->code = 0;
            $result->msg = "HTTP_RESPONSE_NOT_WELL_FORMED";
            return $result;
        }
        //如果TOP返回了错误码,记录到业务错误日志中
        if (isset($respObject->code))
        {
            $logger = new TopLogger;
            $logger->conf["log_file"] = rtrim(TOP_SDK_WORK_DIR, '\\/') . '/' . "logs/top_biz_err_" . $this->appkey . "_" . date("Y-m-d") . ".log";
            $logger->log(array(
                date("Y-m-d H:i:s"),
                $resp
            ));
        }
        return $respObject;
    }
    public function exec($paramsArray)
    {
        if (!isset($paramsArray["method"]))
        {
            trigger_error("No api name passed");
        }
        $inflector = new LtInflector;
        $inflector->conf["separator"] = ".";
        $requestClassName = ucfirst($inflector->camelize(substr($paramsArray["method"], 7))) . "Request";
        if (!class_exists($requestClassName))
        {
            trigger_error("No such api: " . $paramsArray["method"]);
        }
        $session = isset($paramsArray["session"]) ? $paramsArray["session"] : null;
        $req = new $requestClassName;
        foreach($paramsArray as $paraKey => $paraValue)
        {
            $inflector->conf["separator"] = "_";
            $setterMethodName = $inflector->camelize($paraKey);
            $inflector->conf["separator"] = ".";
            $setterMethodName = "set" . $inflector->camelize($setterMethodName);
            if (method_exists($req, $setterMethodName))
            {
                $req->$setterMethodName($paraValue);
            }
        }
        return $this->execute($req, $session);
    }
    private function getClusterTag()
    {
        return substr($this->sdkVersion,0,11)."-cluster".substr($this->sdkVersion,11);
    }
}
Library/Alidayu/SDK/TopLogger.php
New file
@@ -0,0 +1,43 @@
<?php
class TopLogger
{
    public $conf = array(
        "separator" => "\t",
        "log_file" => ""
    );
    private $fileHandle;
    protected function getFileHandle()
    {
        if (null === $this->fileHandle)
        {
            if (empty($this->conf["log_file"]))
            {
                trigger_error("no log file spcified.");
            }
            $logDir = dirname($this->conf["log_file"]);
            if (!is_dir($logDir))
            {
                mkdir($logDir, 0777, true);
            }
            $this->fileHandle = fopen($this->conf["log_file"], "a");
        }
        return $this->fileHandle;
    }
    public function log($logData)
    {
        if ("" == $logData || array() == $logData)
        {
            return false;
        }
        if (is_array($logData))
        {
            $logData = implode($this->conf["separator"], $logData);
        }
        $logData = $logData. "\n";
        fwrite($this->getFileHandle(), $logData);
    }
}
?>
Library/Alidayu/SDK/domain/Area.php
New file
@@ -0,0 +1,35 @@
<?php
/**
 * 地址区域结构
 * @author auto create
 */
class Area
{
    /**
     * 标准行政区域代码.参考:http://www.stats.gov.cn/tjbz/xzqhdm/t20120105_402777427.htm
     **/
    public $id;
    /**
     * 地域名称.如北京市,杭州市,西湖区,每一个area_id 都代表了一个具体的地区.
     **/
    public $name;
    /**
     * 父节点区域标识.如北京市的area_id是110100,朝阳区是北京市的一个区,所以朝阳区的parent_id就是北京市的area_id.
     **/
    public $parent_id;
    /**
     * 区域类型.area区域 1:country/国家;2:province/省/自治区/直辖市;3:city/地区(省下面的地级市);4:district/县/市(县级市)/区;abroad:海外. 比如北京市的area_type = 2,朝阳区是北京市的一个区,所以朝阳区的area_type = 4.
     **/
    public $type;
    /**
     * 具体一个地区的邮编
     **/
    public $zip;
}
?>
Library/Alidayu/SDK/domain/BizResult.php
New file
@@ -0,0 +1,30 @@
<?php
/**
 * 返回结果对象
 * @author auto create
 */
class BizResult
{
    /**
     * 错误码
     **/
    public $err_code;
    /**
     * 返回结果
     **/
    public $model;
    /**
     * 返回信息描述
     **/
    public $msg;
    /**
     * true表示成功,false表示失败
     **/
    public $success;
}
?>
Library/Alidayu/SDK/domain/FcPartnerSmsDetailDto.php
New file
@@ -0,0 +1,50 @@
<?php
/**
 * 1
 * @author auto create
 */
class FcPartnerSmsDetailDto
{
    /**
     * 公共回传参数
     **/
    public $extend;
    /**
     * 短信接收号码
     **/
    public $rec_num;
    /**
     * 短信错误码
     **/
    public $result_code;
    /**
     * 模板编码
     **/
    public $sms_code;
    /**
     * 短信发送内容
     **/
    public $sms_content;
    /**
     * 短信接收时间
     **/
    public $sms_receiver_time;
    /**
     * 短信发送时间
     **/
    public $sms_send_time;
    /**
     * 发送状态 1:等待回执,2:发送失败,3:发送成功
     **/
    public $sms_status;
}
?>
Library/Alidayu/SDK/domain/KfcSearchResult.php
New file
@@ -0,0 +1,29 @@
<?php
/**
 * KFC 关键词过滤匹配结果
 * @author auto create
 */
class KfcSearchResult
{
    /**
     * 过滤后的文本:
当匹配到B等级的词时,文本中的关键词被替换为*号,content即为关键词替换后的文本;
其他情况,content始终为null
     **/
    public $content;
    /**
     * 匹配到的关键词的等级,值为null,或为A、B、C、D。
当匹配不到关键词时,值为null,否则值为A、B、C、D中的一个。
A、B、C、D等级按严重程度从高至低排列。
     **/
    public $level;
    /**
     * 是否匹配到关键词,匹配到则为true.
     **/
    public $matched;
}
?>
Library/Alidayu/SDK/domain/Result.php
New file
@@ -0,0 +1,30 @@
<?php
/**
 * 无
 * @author auto create
 */
class Result
{
    /**
     * 错误码
     **/
    public $code;
    /**
     * 无
     **/
    public $model;
    /**
     * 原因
     **/
    public $msg;
    /**
     * 结果
     **/
    public $success;
}
?>
Library/Alidayu/SDK/domain/Subtask.php
New file
@@ -0,0 +1,25 @@
<?php
/**
 * 批量异步任务的子任务结果
 * @author auto create
 */
class Subtask
{
    /**
     * 标记子任务是否成功。为true表示子任务成功,用户可以按照正确执行的结果格式解析sub_task_result。为false表示子任务失败了,用户需要按照失败的结果格式解析sub_task_result(里面只有sub_code和sub_msg)
     **/
    public $is_success;
    /**
     * 子任务的有效请求参数,以json格式进行key:value的组合
     **/
    public $sub_task_request;
    /**
     * 子任务返回的结果,以json格式进行key:value组合,可以和单个api请求结果解析复用。以获取交易订单详情为例:子任务执行成功返回的结果格式为:{“trade”:{"tid":123456,"seller_nick":"淘宝卖家"}};子任务执行失败结果格式为{"sub_code":"isv.trade-not-exist","sub_msg":"交易订单不存在"}
     **/
    public $sub_task_result;
}
?>
Library/Alidayu/SDK/domain/Task.php
New file
@@ -0,0 +1,52 @@
<?php
/**
 * 批量异步任务结果
 * @author auto create
 */
class Task
{
    /**
     * 下载文件的MD5校验码,通过此校验码可以检查下载的文件是否是完整的。
     **/
    public $check_code;
    /**
     * 任务创建时间
     **/
    public $created;
    /**
     * 大任务结果下载地址。当创建的认任务是大数据量的任务时,获取结果会返回此字段,同时subtasks列表会为空。
通过这个地址可以下载到结果的结构体,格式同普通任务下载的一样。
每次获取到的地址只能下载一次。下载的文件加上后缀名.zip打开。
     **/
    public $download_url;
    /**
     * 此任务是由哪个api产生的
     **/
    public $method;
    /**
     * 定时类型任务的执行时间点
     **/
    public $schedule;
    /**
     * 异步任务处理状态。new(还未开始处理),doing(处理中),done(处理结束)。
     **/
    public $status;
    /**
     * 子任务处理结果,如果任务还没有处理完,返回的结果列表为空。如果任务处理完毕,返回子任务结果列表
     **/
    public $subtasks;
    /**
     * 异步任务id。创建异步任务时返回的任务id号
     **/
    public $task_id;
}
?>
Library/Alidayu/SDK/request/AlibabaAliqinFcFlowChargeProvinceRequest.php
New file
@@ -0,0 +1,98 @@
<?php
/**
 * TOP API: alibaba.aliqin.fc.flow.charge.province request
 *
 * @author auto create
 * @since 1.0, 2016.03.30
 */
class AlibabaAliqinFcFlowChargeProvinceRequest
{
    /**
     * 需要充值的流量
     **/
    private $grade;
    /**
     * 唯一流水号
     **/
    private $outRechargeId;
    /**
     * 手机号
     **/
    private $phoneNum;
    /**
     * 充值原因
     **/
    private $reason;
    private $apiParas = array();
    public function setGrade($grade)
    {
        $this->grade = $grade;
        $this->apiParas["grade"] = $grade;
    }
    public function getGrade()
    {
        return $this->grade;
    }
    public function setOutRechargeId($outRechargeId)
    {
        $this->outRechargeId = $outRechargeId;
        $this->apiParas["out_recharge_id"] = $outRechargeId;
    }
    public function getOutRechargeId()
    {
        return $this->outRechargeId;
    }
    public function setPhoneNum($phoneNum)
    {
        $this->phoneNum = $phoneNum;
        $this->apiParas["phone_num"] = $phoneNum;
    }
    public function getPhoneNum()
    {
        return $this->phoneNum;
    }
    public function setReason($reason)
    {
        $this->reason = $reason;
        $this->apiParas["reason"] = $reason;
    }
    public function getReason()
    {
        return $this->reason;
    }
    public function getApiMethodName()
    {
        return "alibaba.aliqin.fc.flow.charge.province";
    }
    public function getApiParas()
    {
        return $this->apiParas;
    }
    public function check()
    {
        RequestCheckUtil::checkNotNull($this->grade,"grade");
        RequestCheckUtil::checkNotNull($this->outRechargeId,"outRechargeId");
        RequestCheckUtil::checkNotNull($this->phoneNum,"phoneNum");
    }
    public function putOtherTextParam($key, $value) {
        $this->apiParas[$key] = $value;
        $this->$key = $value;
    }
}
Library/Alidayu/SDK/request/AlibabaAliqinFcFlowChargeRequest.php
New file
@@ -0,0 +1,98 @@
<?php
/**
 * TOP API: alibaba.aliqin.fc.flow.charge request
 *
 * @author auto create
 * @since 1.0, 2016.03.30
 */
class AlibabaAliqinFcFlowChargeRequest
{
    /**
     * 需要充值的流量
     **/
    private $grade;
    /**
     * 唯一流水号
     **/
    private $outRechargeId;
    /**
     * 手机号
     **/
    private $phoneNum;
    /**
     * 充值原因
     **/
    private $reason;
    private $apiParas = array();
    public function setGrade($grade)
    {
        $this->grade = $grade;
        $this->apiParas["grade"] = $grade;
    }
    public function getGrade()
    {
        return $this->grade;
    }
    public function setOutRechargeId($outRechargeId)
    {
        $this->outRechargeId = $outRechargeId;
        $this->apiParas["out_recharge_id"] = $outRechargeId;
    }
    public function getOutRechargeId()
    {
        return $this->outRechargeId;
    }
    public function setPhoneNum($phoneNum)
    {
        $this->phoneNum = $phoneNum;
        $this->apiParas["phone_num"] = $phoneNum;
    }
    public function getPhoneNum()
    {
        return $this->phoneNum;
    }
    public function setReason($reason)
    {
        $this->reason = $reason;
        $this->apiParas["reason"] = $reason;
    }
    public function getReason()
    {
        return $this->reason;
    }
    public function getApiMethodName()
    {
        return "alibaba.aliqin.fc.flow.charge";
    }
    public function getApiParas()
    {
        return $this->apiParas;
    }
    public function check()
    {
        RequestCheckUtil::checkNotNull($this->grade,"grade");
        RequestCheckUtil::checkNotNull($this->outRechargeId,"outRechargeId");
        RequestCheckUtil::checkNotNull($this->phoneNum,"phoneNum");
    }
    public function putOtherTextParam($key, $value) {
        $this->apiParas[$key] = $value;
        $this->$key = $value;
    }
}
Library/Alidayu/SDK/request/AlibabaAliqinFcFlowGradeRequest.php
New file
@@ -0,0 +1,32 @@
<?php
/**
 * TOP API: alibaba.aliqin.fc.flow.grade request
 *
 * @author auto create
 * @since 1.0, 2016.03.30
 */
class AlibabaAliqinFcFlowGradeRequest
{
    private $apiParas = array();
    public function getApiMethodName()
    {
        return "alibaba.aliqin.fc.flow.grade";
    }
    public function getApiParas()
    {
        return $this->apiParas;
    }
    public function check()
    {
    }
    public function putOtherTextParam($key, $value) {
        $this->apiParas[$key] = $value;
        $this->$key = $value;
    }
}
Library/Alidayu/SDK/request/AlibabaAliqinFcFlowQueryRequest.php
New file
@@ -0,0 +1,47 @@
<?php
/**
 * TOP API: alibaba.aliqin.fc.flow.query request
 *
 * @author auto create
 * @since 1.0, 2016.03.30
 */
class AlibabaAliqinFcFlowQueryRequest
{
    /**
     * 唯一流水号
     **/
    private $outId;
    private $apiParas = array();
    public function setOutId($outId)
    {
        $this->outId = $outId;
        $this->apiParas["out_id"] = $outId;
    }
    public function getOutId()
    {
        return $this->outId;
    }
    public function getApiMethodName()
    {
        return "alibaba.aliqin.fc.flow.query";
    }
    public function getApiParas()
    {
        return $this->apiParas;
    }
    public function check()
    {
    }
    public function putOtherTextParam($key, $value) {
        $this->apiParas[$key] = $value;
        $this->$key = $value;
    }
}
Library/Alidayu/SDK/request/AlibabaAliqinFcSmsNumQueryRequest.php
New file
@@ -0,0 +1,115 @@
<?php
/**
 * TOP API: alibaba.aliqin.fc.sms.num.query request
 *
 * @author auto create
 * @since 1.0, 2016.03.01
 */
class AlibabaAliqinFcSmsNumQueryRequest
{
    /**
     * 短信发送流水
     **/
    private $bizId;
    /**
     * 分页参数,页码
     **/
    private $currentPage;
    /**
     * 分页参数,每页数量。最大值50
     **/
    private $pageSize;
    /**
     * 短信发送日期,支持近30天记录查询,格式yyyyMMdd
     **/
    private $queryDate;
    /**
     * 短信接收号码
     **/
    private $recNum;
    private $apiParas = array();
    public function setBizId($bizId)
    {
        $this->bizId = $bizId;
        $this->apiParas["biz_id"] = $bizId;
    }
    public function getBizId()
    {
        return $this->bizId;
    }
    public function setCurrentPage($currentPage)
    {
        $this->currentPage = $currentPage;
        $this->apiParas["current_page"] = $currentPage;
    }
    public function getCurrentPage()
    {
        return $this->currentPage;
    }
    public function setPageSize($pageSize)
    {
        $this->pageSize = $pageSize;
        $this->apiParas["page_size"] = $pageSize;
    }
    public function getPageSize()
    {
        return $this->pageSize;
    }
    public function setQueryDate($queryDate)
    {
        $this->queryDate = $queryDate;
        $this->apiParas["query_date"] = $queryDate;
    }
    public function getQueryDate()
    {
        return $this->queryDate;
    }
    public function setRecNum($recNum)
    {
        $this->recNum = $recNum;
        $this->apiParas["rec_num"] = $recNum;
    }
    public function getRecNum()
    {
        return $this->recNum;
    }
    public function getApiMethodName()
    {
        return "alibaba.aliqin.fc.sms.num.query";
    }
    public function getApiParas()
    {
        return $this->apiParas;
    }
    public function check()
    {
        RequestCheckUtil::checkNotNull($this->currentPage,"currentPage");
        RequestCheckUtil::checkNotNull($this->pageSize,"pageSize");
        RequestCheckUtil::checkNotNull($this->queryDate,"queryDate");
        RequestCheckUtil::checkNotNull($this->recNum,"recNum");
    }
    public function putOtherTextParam($key, $value) {
        $this->apiParas[$key] = $value;
        $this->$key = $value;
    }
}
Library/Alidayu/SDK/request/AlibabaAliqinFcSmsNumSendRequest.php
New file
@@ -0,0 +1,131 @@
<?php
/**
 * TOP API: alibaba.aliqin.fc.sms.num.send request
 *
 * @author auto create
 * @since 1.0, 2016.05.24
 */
class AlibabaAliqinFcSmsNumSendRequest
{
    /**
     * 公共回传参数,在“消息返回”中会透传回该参数;举例:用户可以传入自己下级的会员ID,在消息返回时,该会员ID会包含在内,用户可以根据该会员ID识别是哪位会员使用了你的应用
     **/
    private $extend;
    /**
     * 短信接收号码。支持单个或多个手机号码,传入号码为11位手机号码,不能加0或+86。群发短信需传入多个号码,以英文逗号分隔,一次调用最多传入200个号码。示例:18600000000,13911111111,13322222222
     **/
    private $recNum;
    /**
     * 短信签名,传入的短信签名必须是在阿里大鱼“管理中心-短信签名管理”中的可用签名。如“阿里大鱼”已在短信签名管理中通过审核,则可传入”阿里大鱼“(传参时去掉引号)作为短信签名。短信效果示例:【阿里大鱼】欢迎使用阿里大鱼服务。
     **/
    private $smsFreeSignName;
    /**
     * 短信模板变量,传参规则{"key":"value"},key的名字须和申请模板中的变量名一致,多个变量之间以逗号隔开。示例:针对模板“验证码${code},您正在进行${product}身份验证,打死不要告诉别人哦!”,传参时需传入{"code":"1234","product":"alidayu"}
     **/
    private $smsParam;
    /**
     * 短信模板ID,传入的模板必须是在阿里大鱼“管理中心-短信模板管理”中的可用模板。示例:SMS_585014
     **/
    private $smsTemplateCode;
    /**
     * 短信类型,传入值请填写normal
     **/
    private $smsType;
    private $apiParas = array();
    public function setExtend($extend)
    {
        $this->extend = $extend;
        $this->apiParas["extend"] = $extend;
    }
    public function getExtend()
    {
        return $this->extend;
    }
    public function setRecNum($recNum)
    {
        $this->recNum = $recNum;
        $this->apiParas["rec_num"] = $recNum;
    }
    public function getRecNum()
    {
        return $this->recNum;
    }
    public function setSmsFreeSignName($smsFreeSignName)
    {
        $this->smsFreeSignName = $smsFreeSignName;
        $this->apiParas["sms_free_sign_name"] = $smsFreeSignName;
    }
    public function getSmsFreeSignName()
    {
        return $this->smsFreeSignName;
    }
    public function setSmsParam($smsParam)
    {
        $this->smsParam = $smsParam;
        $this->apiParas["sms_param"] = $smsParam;
    }
    public function getSmsParam()
    {
        return $this->smsParam;
    }
    public function setSmsTemplateCode($smsTemplateCode)
    {
        $this->smsTemplateCode = $smsTemplateCode;
        $this->apiParas["sms_template_code"] = $smsTemplateCode;
    }
    public function getSmsTemplateCode()
    {
        return $this->smsTemplateCode;
    }
    public function setSmsType($smsType)
    {
        $this->smsType = $smsType;
        $this->apiParas["sms_type"] = $smsType;
    }
    public function getSmsType()
    {
        return $this->smsType;
    }
    public function getApiMethodName()
    {
        return "alibaba.aliqin.fc.sms.num.send";
    }
    public function getApiParas()
    {
        return $this->apiParas;
    }
    public function check()
    {
        RequestCheckUtil::checkNotNull($this->recNum,"recNum");
        RequestCheckUtil::checkNotNull($this->smsFreeSignName,"smsFreeSignName");
        RequestCheckUtil::checkNotNull($this->smsTemplateCode,"smsTemplateCode");
        RequestCheckUtil::checkNotNull($this->smsType,"smsType");
    }
    public function putOtherTextParam($key, $value) {
        $this->apiParas[$key] = $value;
        $this->$key = $value;
    }
}
Library/Alidayu/SDK/request/AlibabaAliqinFcTtsNumSinglecallRequest.php
New file
@@ -0,0 +1,114 @@
<?php
/**
 * TOP API: alibaba.aliqin.fc.tts.num.singlecall request
 *
 * @author auto create
 * @since 1.0, 2016.05.24
 */
class AlibabaAliqinFcTtsNumSinglecallRequest
{
    /**
     * 被叫号码,支持国内手机号与固话号码,格式如下057188773344,13911112222,4001112222,95500
     **/
    private $calledNum;
    /**
     * 被叫号显,传入的显示号码必须是阿里大鱼“管理中心-号码管理”中申请或购买的号码
     **/
    private $calledShowNum;
    /**
     * 公共回传参数,在“消息返回”中会透传回该参数;举例:用户可以传入自己下级的会员ID,在消息返回时,该会员ID会包含在内,用户可以根据该会员ID识别是哪位会员使用了你的应用
     **/
    private $extend;
    /**
     * TTS模板ID,传入的模板必须是在阿里大鱼“管理中心-语音TTS模板管理”中的可用模板
     **/
    private $ttsCode;
    /**
     * 文本转语音(TTS)模板变量,传参规则{"key":"value"},key的名字须和TTS模板中的变量名一致,多个变量之间以逗号隔开,示例:{"name":"xiaoming","code":"1234"}
     **/
    private $ttsParam;
    private $apiParas = array();
    public function setCalledNum($calledNum)
    {
        $this->calledNum = $calledNum;
        $this->apiParas["called_num"] = $calledNum;
    }
    public function getCalledNum()
    {
        return $this->calledNum;
    }
    public function setCalledShowNum($calledShowNum)
    {
        $this->calledShowNum = $calledShowNum;
        $this->apiParas["called_show_num"] = $calledShowNum;
    }
    public function getCalledShowNum()
    {
        return $this->calledShowNum;
    }
    public function setExtend($extend)
    {
        $this->extend = $extend;
        $this->apiParas["extend"] = $extend;
    }
    public function getExtend()
    {
        return $this->extend;
    }
    public function setTtsCode($ttsCode)
    {
        $this->ttsCode = $ttsCode;
        $this->apiParas["tts_code"] = $ttsCode;
    }
    public function getTtsCode()
    {
        return $this->ttsCode;
    }
    public function setTtsParam($ttsParam)
    {
        $this->ttsParam = $ttsParam;
        $this->apiParas["tts_param"] = $ttsParam;
    }
    public function getTtsParam()
    {
        return $this->ttsParam;
    }
    public function getApiMethodName()
    {
        return "alibaba.aliqin.fc.tts.num.singlecall";
    }
    public function getApiParas()
    {
        return $this->apiParas;
    }
    public function check()
    {
        RequestCheckUtil::checkNotNull($this->calledNum,"calledNum");
        RequestCheckUtil::checkNotNull($this->calledShowNum,"calledShowNum");
        RequestCheckUtil::checkNotNull($this->ttsCode,"ttsCode");
    }
    public function putOtherTextParam($key, $value) {
        $this->apiParas[$key] = $value;
        $this->$key = $value;
    }
}
Library/Alidayu/SDK/request/AlibabaAliqinFcVoiceNumDoublecallRequest.php
New file
@@ -0,0 +1,131 @@
<?php
/**
 * TOP API: alibaba.aliqin.fc.voice.num.doublecall request
 *
 * @author auto create
 * @since 1.0, 2016.03.06
 */
class AlibabaAliqinFcVoiceNumDoublecallRequest
{
    /**
     * 被叫号码,支持国内手机号与固话号码,格式如下057188773344,13911112222,4001112222,95500
     **/
    private $calledNum;
    /**
     * 被叫号码侧的号码显示,传入的显示号码可以是阿里大鱼“管理中心-号码管理”中申请通过的号码。显示号码格式如下057188773344,4001112222,95500。显示号码也可以为主叫号码。
     **/
    private $calledShowNum;
    /**
     * 主叫号码,支持国内手机号与固话号码,格式如下057188773344,13911112222,4001112222,95500
     **/
    private $callerNum;
    /**
     * 主叫号码侧的号码显示,传入的显示号码必须是阿里大鱼“管理中心-号码管理”中申请通过的号码。显示号码格式如下057188773344,4001112222,95500
     **/
    private $callerShowNum;
    /**
     * 公共回传参数,在“消息返回”中会透传回该参数;举例:用户可以传入自己下级的会员ID,在消息返回时,该会员ID会包含在内,用户可以根据该会员ID识别是哪位会员使用了你的应用
     **/
    private $extend;
    /**
     * 通话超时时长,如接通后到达120秒时,通话会因为超时自动挂断。若无需设置超时时长,可不传。
     **/
    private $sessionTimeOut;
    private $apiParas = array();
    public function setCalledNum($calledNum)
    {
        $this->calledNum = $calledNum;
        $this->apiParas["called_num"] = $calledNum;
    }
    public function getCalledNum()
    {
        return $this->calledNum;
    }
    public function setCalledShowNum($calledShowNum)
    {
        $this->calledShowNum = $calledShowNum;
        $this->apiParas["called_show_num"] = $calledShowNum;
    }
    public function getCalledShowNum()
    {
        return $this->calledShowNum;
    }
    public function setCallerNum($callerNum)
    {
        $this->callerNum = $callerNum;
        $this->apiParas["caller_num"] = $callerNum;
    }
    public function getCallerNum()
    {
        return $this->callerNum;
    }
    public function setCallerShowNum($callerShowNum)
    {
        $this->callerShowNum = $callerShowNum;
        $this->apiParas["caller_show_num"] = $callerShowNum;
    }
    public function getCallerShowNum()
    {
        return $this->callerShowNum;
    }
    public function setExtend($extend)
    {
        $this->extend = $extend;
        $this->apiParas["extend"] = $extend;
    }
    public function getExtend()
    {
        return $this->extend;
    }
    public function setSessionTimeOut($sessionTimeOut)
    {
        $this->sessionTimeOut = $sessionTimeOut;
        $this->apiParas["session_time_out"] = $sessionTimeOut;
    }
    public function getSessionTimeOut()
    {
        return $this->sessionTimeOut;
    }
    public function getApiMethodName()
    {
        return "alibaba.aliqin.fc.voice.num.doublecall";
    }
    public function getApiParas()
    {
        return $this->apiParas;
    }
    public function check()
    {
        RequestCheckUtil::checkNotNull($this->calledNum,"calledNum");
        RequestCheckUtil::checkNotNull($this->calledShowNum,"calledShowNum");
        RequestCheckUtil::checkNotNull($this->callerNum,"callerNum");
        RequestCheckUtil::checkNotNull($this->callerShowNum,"callerShowNum");
    }
    public function putOtherTextParam($key, $value) {
        $this->apiParas[$key] = $value;
        $this->$key = $value;
    }
}
Library/Alidayu/SDK/request/AlibabaAliqinFcVoiceNumSinglecallRequest.php
New file
@@ -0,0 +1,98 @@
<?php
/**
 * TOP API: alibaba.aliqin.fc.voice.num.singlecall request
 *
 * @author auto create
 * @since 1.0, 2016.03.01
 */
class AlibabaAliqinFcVoiceNumSinglecallRequest
{
    /**
     * 被叫号码,支持国内手机号与固话号码,格式如下057188773344,13911112222,4001112222,95500
     **/
    private $calledNum;
    /**
     * 被叫号显,传入的显示号码必须是阿里大鱼“管理中心-号码管理”中申请通过的号码
     **/
    private $calledShowNum;
    /**
     * 公共回传参数,在“消息返回”中会透传回该参数;举例:用户可以传入自己下级的会员ID,在消息返回时,该会员ID会包含在内,用户可以根据该会员ID识别是哪位会员使用了你的应用
     **/
    private $extend;
    /**
     * 语音文件ID,传入的语音文件必须是在阿里大鱼“管理中心-语音文件管理”中的可用语音文件
     **/
    private $voiceCode;
    private $apiParas = array();
    public function setCalledNum($calledNum)
    {
        $this->calledNum = $calledNum;
        $this->apiParas["called_num"] = $calledNum;
    }
    public function getCalledNum()
    {
        return $this->calledNum;
    }
    public function setCalledShowNum($calledShowNum)
    {
        $this->calledShowNum = $calledShowNum;
        $this->apiParas["called_show_num"] = $calledShowNum;
    }
    public function getCalledShowNum()
    {
        return $this->calledShowNum;
    }
    public function setExtend($extend)
    {
        $this->extend = $extend;
        $this->apiParas["extend"] = $extend;
    }
    public function getExtend()
    {
        return $this->extend;
    }
    public function setVoiceCode($voiceCode)
    {
        $this->voiceCode = $voiceCode;
        $this->apiParas["voice_code"] = $voiceCode;
    }
    public function getVoiceCode()
    {
        return $this->voiceCode;
    }
    public function getApiMethodName()
    {
        return "alibaba.aliqin.fc.voice.num.singlecall";
    }
    public function getApiParas()
    {
        return $this->apiParas;
    }
    public function check()
    {
        RequestCheckUtil::checkNotNull($this->calledNum,"calledNum");
        RequestCheckUtil::checkNotNull($this->calledShowNum,"calledShowNum");
        RequestCheckUtil::checkNotNull($this->voiceCode,"voiceCode");
    }
    public function putOtherTextParam($key, $value) {
        $this->apiParas[$key] = $value;
        $this->$key = $value;
    }
}
Library/Alidayu/SDK/request/AppipGetRequest.php
New file
@@ -0,0 +1,32 @@
<?php
/**
 * TOP API: taobao.appip.get request
 *
 * @author auto create
 * @since 1.0, 2014.11.26
 */
class AppipGetRequest
{
    private $apiParas = array();
    public function getApiMethodName()
    {
        return "taobao.appip.get";
    }
    public function getApiParas()
    {
        return $this->apiParas;
    }
    public function check()
    {
    }
    public function putOtherTextParam($key, $value) {
        $this->apiParas[$key] = $value;
        $this->$key = $value;
    }
}
Library/Alidayu/SDK/request/AreasGetRequest.php
New file
@@ -0,0 +1,48 @@
<?php
/**
 * TOP API: taobao.areas.get request
 *
 * @author auto create
 * @since 1.0, 2016.04.13
 */
class AreasGetRequest
{
    /**
     * 需返回的字段列表.可选值:Area 结构中的所有字段;多个字段之间用","分隔.如:id,type,name,parent_id,zip.
     **/
    private $fields;
    private $apiParas = array();
    public function setFields($fields)
    {
        $this->fields = $fields;
        $this->apiParas["fields"] = $fields;
    }
    public function getFields()
    {
        return $this->fields;
    }
    public function getApiMethodName()
    {
        return "taobao.areas.get";
    }
    public function getApiParas()
    {
        return $this->apiParas;
    }
    public function check()
    {
        RequestCheckUtil::checkNotNull($this->fields,"fields");
    }
    public function putOtherTextParam($key, $value) {
        $this->apiParas[$key] = $value;
        $this->$key = $value;
    }
}
Library/Alidayu/SDK/request/HttpdnsGetRequest.php
New file
@@ -0,0 +1,32 @@
<?php
/**
 * TOP API: taobao.httpdns.get request
 *
 * @author auto create
 * @since 1.0, 2016.03.24
 */
class HttpdnsGetRequest
{
    private $apiParas = array();
    public function getApiMethodName()
    {
        return "taobao.httpdns.get";
    }
    public function getApiParas()
    {
        return $this->apiParas;
    }
    public function check()
    {
    }
    public function putOtherTextParam($key, $value) {
        $this->apiParas[$key] = $value;
        $this->$key = $value;
    }
}
Library/Alidayu/SDK/request/KfcKeywordSearchRequest.php
New file
@@ -0,0 +1,85 @@
<?php
/**
 * TOP API: taobao.kfc.keyword.search request
 *
 * @author auto create
 * @since 1.0, 2016.03.19
 */
class KfcKeywordSearchRequest
{
    /**
     * 应用点,分为一级应用点、二级应用点。其中一级应用点通常是指某一个系统或产品,比如淘宝的商品应用(taobao_auction);二级应用点,是指一级应用点下的具体的分类,比如商品标题(title)、商品描述(content)。不同的二级应用可以设置不同关键词。
这里的apply参数是由一级应用点与二级应用点合起来的字符(一级应用点+"."+二级应用点),如taobao_auction.title。
通常apply参数是不需要传递的。如有特殊需求(比如特殊的过滤需求,需要自己维护一套自己词库),需传递此参数。
     **/
    private $apply;
    /**
     * 需要过滤的文本信息
     **/
    private $content;
    /**
     * 发布信息的淘宝会员名,可以不传
     **/
    private $nick;
    private $apiParas = array();
    public function setApply($apply)
    {
        $this->apply = $apply;
        $this->apiParas["apply"] = $apply;
    }
    public function getApply()
    {
        return $this->apply;
    }
    public function setContent($content)
    {
        $this->content = $content;
        $this->apiParas["content"] = $content;
    }
    public function getContent()
    {
        return $this->content;
    }
    public function setNick($nick)
    {
        $this->nick = $nick;
        $this->apiParas["nick"] = $nick;
    }
    public function getNick()
    {
        return $this->nick;
    }
    public function getApiMethodName()
    {
        return "taobao.kfc.keyword.search";
    }
    public function getApiParas()
    {
        return $this->apiParas;
    }
    public function check()
    {
        RequestCheckUtil::checkNotNull($this->content,"content");
    }
    public function putOtherTextParam($key, $value) {
        $this->apiParas[$key] = $value;
        $this->$key = $value;
    }
}
Library/Alidayu/SDK/request/TimeGetRequest.php
New file
@@ -0,0 +1,32 @@
<?php
/**
 * TOP API: taobao.time.get request
 *
 * @author auto create
 * @since 1.0, 2016.03.28
 */
class TimeGetRequest
{
    private $apiParas = array();
    public function getApiMethodName()
    {
        return "taobao.time.get";
    }
    public function getApiParas()
    {
        return $this->apiParas;
    }
    public function check()
    {
    }
    public function putOtherTextParam($key, $value) {
        $this->apiParas[$key] = $value;
        $this->$key = $value;
    }
}
Library/Alidayu/SDK/request/TopAuthTokenCreateRequest.php
New file
@@ -0,0 +1,64 @@
<?php
/**
 * TOP API: taobao.top.auth.token.create request
 *
 * @author auto create
 * @since 1.0, 2016.04.15
 */
class TopAuthTokenCreateRequest
{
    /**
     * 授权code,grantType==authorization_code 时需要
     **/
    private $code;
    /**
     * 与生成code的uuid配对
     **/
    private $uuid;
    private $apiParas = array();
    public function setCode($code)
    {
        $this->code = $code;
        $this->apiParas["code"] = $code;
    }
    public function getCode()
    {
        return $this->code;
    }
    public function setUuid($uuid)
    {
        $this->uuid = $uuid;
        $this->apiParas["uuid"] = $uuid;
    }
    public function getUuid()
    {
        return $this->uuid;
    }
    public function getApiMethodName()
    {
        return "taobao.top.auth.token.create";
    }
    public function getApiParas()
    {
        return $this->apiParas;
    }
    public function check()
    {
        RequestCheckUtil::checkNotNull($this->code,"code");
    }
    public function putOtherTextParam($key, $value) {
        $this->apiParas[$key] = $value;
        $this->$key = $value;
    }
}
Library/Alidayu/SDK/request/TopAuthTokenRefreshRequest.php
New file
@@ -0,0 +1,48 @@
<?php
/**
 * TOP API: taobao.top.auth.token.refresh request
 *
 * @author auto create
 * @since 1.0, 2015.08.20
 */
class TopAuthTokenRefreshRequest
{
    /**
     * grantType==refresh_token 时需要
     **/
    private $refreshToken;
    private $apiParas = array();
    public function setRefreshToken($refreshToken)
    {
        $this->refreshToken = $refreshToken;
        $this->apiParas["refresh_token"] = $refreshToken;
    }
    public function getRefreshToken()
    {
        return $this->refreshToken;
    }
    public function getApiMethodName()
    {
        return "taobao.top.auth.token.refresh";
    }
    public function getApiParas()
    {
        return $this->apiParas;
    }
    public function check()
    {
        RequestCheckUtil::checkNotNull($this->refreshToken,"refreshToken");
    }
    public function putOtherTextParam($key, $value) {
        $this->apiParas[$key] = $value;
        $this->$key = $value;
    }
}
Library/Alidayu/SDK/request/TopIpoutGetRequest.php
New file
@@ -0,0 +1,32 @@
<?php
/**
 * TOP API: taobao.top.ipout.get request
 *
 * @author auto create
 * @since 1.0, 2015.09.07
 */
class TopIpoutGetRequest
{
    private $apiParas = array();
    public function getApiMethodName()
    {
        return "taobao.top.ipout.get";
    }
    public function getApiParas()
    {
        return $this->apiParas;
    }
    public function check()
    {
    }
    public function putOtherTextParam($key, $value) {
        $this->apiParas[$key] = $value;
        $this->$key = $value;
    }
}
Library/Alidayu/SDK/request/TopSecretGetRequest.php
New file
@@ -0,0 +1,64 @@
<?php
/**
 * TOP API: taobao.top.secret.get request
 *
 * @author auto create
 * @since 1.0, 2016.04.06
 */
class TopSecretGetRequest
{
    /**
     * 伪随机数
     **/
    private $randomNum;
    /**
     * 秘钥版本号
     **/
    private $secretVersion;
    private $apiParas = array();
    public function setRandomNum($randomNum)
    {
        $this->randomNum = $randomNum;
        $this->apiParas["random_num"] = $randomNum;
    }
    public function getRandomNum()
    {
        return $this->randomNum;
    }
    public function setSecretVersion($secretVersion)
    {
        $this->secretVersion = $secretVersion;
        $this->apiParas["secret_version"] = $secretVersion;
    }
    public function getSecretVersion()
    {
        return $this->secretVersion;
    }
    public function getApiMethodName()
    {
        return "taobao.top.secret.get";
    }
    public function getApiParas()
    {
        return $this->apiParas;
    }
    public function check()
    {
        RequestCheckUtil::checkNotNull($this->randomNum,"randomNum");
    }
    public function putOtherTextParam($key, $value) {
        $this->apiParas[$key] = $value;
        $this->$key = $value;
    }
}
Library/Alidayu/SDK/request/TopatsResultGetRequest.php
New file
@@ -0,0 +1,48 @@
<?php
/**
 * TOP API: taobao.topats.result.get request
 *
 * @author auto create
 * @since 1.0, 2014.04.11
 */
class TopatsResultGetRequest
{
    /**
     * 任务id号,创建任务时返回的task_id
     **/
    private $taskId;
    private $apiParas = array();
    public function setTaskId($taskId)
    {
        $this->taskId = $taskId;
        $this->apiParas["task_id"] = $taskId;
    }
    public function getTaskId()
    {
        return $this->taskId;
    }
    public function getApiMethodName()
    {
        return "taobao.topats.result.get";
    }
    public function getApiParas()
    {
        return $this->apiParas;
    }
    public function check()
    {
        RequestCheckUtil::checkNotNull($this->taskId,"taskId");
    }
    public function putOtherTextParam($key, $value) {
        $this->apiParas[$key] = $value;
        $this->$key = $value;
    }
}
Library/Alidayu/SDK/request/TopatsTaskDeleteRequest.php
New file
@@ -0,0 +1,48 @@
<?php
/**
 * TOP API: taobao.topats.task.delete request
 *
 * @author auto create
 * @since 1.0, 2014.03.27
 */
class TopatsTaskDeleteRequest
{
    /**
     * 需要取消的任务ID
     **/
    private $taskId;
    private $apiParas = array();
    public function setTaskId($taskId)
    {
        $this->taskId = $taskId;
        $this->apiParas["task_id"] = $taskId;
    }
    public function getTaskId()
    {
        return $this->taskId;
    }
    public function getApiMethodName()
    {
        return "taobao.topats.task.delete";
    }
    public function getApiParas()
    {
        return $this->apiParas;
    }
    public function check()
    {
        RequestCheckUtil::checkNotNull($this->taskId,"taskId");
    }
    public function putOtherTextParam($key, $value) {
        $this->apiParas[$key] = $value;
        $this->$key = $value;
    }
}
Library/SMS/Config/app.php
New file
@@ -0,0 +1,21 @@
<?php
/**
 * 请在下面放置任何您需要的应用配置
 */
return array(
    /**
     * 应用接口层的统一参数
     */
    'apiCommonRules' => array(//'sign' => array('name' => 'sign', 'require' => true),
    ),
    "SMSService" => array(
        "accountSid"   => "",  //主帐号
        "accountToken" => "",  //主帐号Token
        "appId"        => "",  //应用Id
        "serverPort"   => "",  //请求端口 默认:8883
        "serverIP"     => ""   //请求地址不需要写https:// 默认:sandboxapp.cloopen.com
    )
);
Library/SMS/Demo.php
New file
@@ -0,0 +1,34 @@
<?php
//初始化SMS_Lite传入配置文件地址,第二个参数为是否开启debug模式开启debug模式(默认false)会把返回结果打印出来(生产环境请不要进行设置)
$SMS = new SMS_Lite("app.SMSService");
//发送模板短信
$SMS->sendTemplateSMS("手机号码", "内容数据", "模板Id");
//短信模板查询
$SMS->QuerySMSTemplate("模板ID");
//语音验证码
$SMS->voiceVerify("验证码内容", "循环播放次数", "接收号码", "显示的主叫号码", "营销外呼状态通知回调地址", '语言类型', '第三方私有数据');
//语音文件上传
$SMS->MediaFileUpload("文件名", "文件二进制数据");
//话单下载 前一天的数据(从00:00 – 23:59)
$SMS->billRecords("话单规则", "客户的查询条件");
//IVR外呼
$SMS->ivrDial("待呼叫号码", "用户数据", "是否录音");
//外呼通知
$SMS->landingCall("被叫号码", "语音文件名称", "文本内容", "显示的主叫号码", "循环播放次数", "外呼通知状态通知回调地址", '用户私有数据', '最大通话时长', '发音速度', '音量', '音调', '背景音编号');
//主帐号信息查询
$SMS->queryAccountInfo();
//呼叫状态查询
$SMS->QueryCallState("callid", "查询结果通知的回调url地址");
Library/SMS/Lite.php
New file
@@ -0,0 +1,297 @@
<?php
/**
 * 2016/1/8 容联云通讯拓展 @喵了个咪<wenzhenxi@vip.qq.com>
 * 支持容联云通讯所有PHPSDK可用内容
 */
class SMS_Lite {
    //主帐号
    private $accountSid = '';
    //主帐号Token
    private $accountToken = '';
    //应用Id
    private $appId = '';
    //REST版本号
    private $softVersion = '2013-12-26';
    //请求端口
    private $serverPort = '8883';
    //请求地址,格式如下,不需要写https://
    private $serverIP = 'sandboxapp.cloopen.com';
    //SDK实例
    private $SMS_SDK_REST;
    //DEBUG
    private $debug;
    /**
     * SMS_Lite 构造方法初始化配置
     *
     * @param  $cofAddress string 配置文件地址
     * @param  $debug      bool   是否开启调试模式
     */
    public function __construct($cofAddress, $debug = false) {
        $this->debug = $debug;
        //获得配置项
        $config = DI()->config->get($cofAddress);
        //配置项是否存在
        if (!$config) {
            throw new PhalApi_Exception_BadRequest(T('Config There is no'));
        }
        //主帐号是否配置
        if ($this->getIndex($config, 'accountSid')) {
            $this->accountSid = $config['accountSid'];
        } else {
            throw new PhalApi_Exception_BadRequest(T('accountSid There is no'));
        }
        //主帐号Token是否配置
        if ($this->getIndex($config, 'accountToken')) {
            $this->accountToken = $config['accountToken'];
        } else {
            throw new PhalApi_Exception_BadRequest(T('accountSid There is no'));
        }
        //应用Id是否配置
        if ($this->getIndex($config, 'appId')) {
            $this->appId = $config['appId'];
        } else {
            throw new PhalApi_Exception_BadRequest(T('accountSid There is no'));
        }
        //请求端口
        if ($this->getIndex($config, 'serverPort')) {
            $this->serverPort = $config['serverPort'];
        }
        //请求地址
        if ($this->getIndex($config, 'serverIP')) {
            $this->serverIP = $config['serverIP'];
        }
        //初始化SDK
        $this->SMS_SDK_REST = new SMS_SDK_REST($this->serverIP, $this->serverPort, $this->softVersion);
        //设置主帐号
        $this->SMS_SDK_REST->setAccount($this->accountSid, $this->accountToken);
        //设置应用ID
        $this->SMS_SDK_REST->setAppId($this->appId);
    }
    /**
     * 语音验证码
     *
     * @param verifyCode 验证码内容,为数字和英文字母,不区分大小写,长度4-8位
     * @param playTimes  播放次数,1-3次
     * @param to         接收号码
     * @param displayNum 显示的主叫号码
     * @param respUrl    语音验证码状态通知回调地址,云通讯平台将向该Url地址发送呼叫结果通知
     * @param lang       语言类型。取值en(英文)、zh(中文),默认值zh。
     * @param userData   第三方私有数据
     */
    function voiceVerify($verifyCode, $playTimes, $to, $displayNum, $respUrl, $lang, $userData) {
        //调用语音验证码接口
        $result = $this->SMS_SDK_REST->voiceVerify($verifyCode, $playTimes, $to, $displayNum, $respUrl, $lang, $userData);
        if ($result == NULL) {
            throw new PhalApi_Exception_BadRequest(T("Error SMS_SDK_REST"));
        }
        //如果是Debug模式则打印返回信息
        if ($this->debug) {
            $this->showarr($result);
        }
        return $result;
    }
    /**
     * 发送模板短信
     *
     * @param to      手机号码集合,用英文逗号分开
     * @param datas   内容数据 格式为数组 例如:array('Marry','Alon'),如不需替换请填 null
     * @param $tempId 模板Id
     */
    function sendTemplateSMS($to, $datas, $tempId) {
        // 发送模板短信
        $result = $this->SMS_SDK_REST->sendTemplateSMS($to, $datas, $tempId);
        if ($result == NULL) {
            throw new PhalApi_Exception_BadRequest(T("Error SMS_SDK_REST"));
        }
        //如果是Debug模式则打印返回信息
        if ($this->debug) {
            $this->showarr($result);
        }
        return $result;
    }
    /**
     * 短信模板查询
     *
     * @param templateId     模板ID
     */
    function QuerySMSTemplate($templateId) {
        // 调用短信模板查询接口
        $result = $this->SMS_SDK_REST->QuerySMSTemplate($templateId);
        if ($result == NULL) {
            throw new PhalApi_Exception_BadRequest(T("Error SMS_SDK_REST"));
        }
        if ($this->debug) {
            $this->showarr($result);
        }
        return $result;
    }
    /**
     * 呼叫状态查询
     *
     * @param callid     呼叫Id
     * @param action     查询结果通知的回调url地址
     */
    function QueryCallState($callid, $action) {
        // 调用呼叫状态查询接口
        $result = $this->SMS_SDK_REST->QueryCallState($callid, $action);
        if ($result == NULL) {
            throw new PhalApi_Exception_BadRequest(T("Error SMS_SDK_REST"));
        }
        if ($this->debug) {
            $this->showarr($result);
        }
        return $result;
    }
    /**
     * 主帐号信息查询
     */
    function queryAccountInfo() {
        // 调用主帐号信息查询接口
        $result = $this->SMS_SDK_REST->queryAccountInfo();
        if ($result == NULL) {
            throw new PhalApi_Exception_BadRequest(T("Error SMS_SDK_REST"));
        }
        if ($this->debug) {
            $this->showarr($result);
        }
        return $result;
    }
    /**
     * 语音文件上传
     *
     * @param filename     文件名
     * @param path         文件所在路径
     */
    function MediaFileUpload($filename, $path) {
        $filePath = $path;
        $fh       = fopen($filePath, "rb");
        $body     = fread($fh, filesize($filePath));
        fclose($fh);
        // 调用语音文件上传接口
        $result = $this->SMS_SDK_REST->MediaFileUpload($filename, $body);
        if ($result == NULL) {
            throw new PhalApi_Exception_BadRequest(T("Error SMS_SDK_REST"));
        }
        if ($this->debug) {
            $this->showarr($result);
        }
        return $result;
    }
    /**
     * 外呼通知
     *
     * @param to          被叫号码
     * @param mediaName   语音文件名称,格式 wav。与mediaTxt不能同时为空。当不为空时mediaTxt属性失效。
     * @param mediaTxt    文本内容
     * @param displayNum  显示的主叫号码
     * @param playTimes   循环播放次数,1-3次,默认播放1次。
     * @param respUrl     外呼通知状态通知回调地址,云通讯平台将向该Url地址发送呼叫结果通知。
     * @param userData    用户私有数据
     * @param maxCallTime 最大通话时长
     * @param speed       发音速度
     * @param volume      音量
     * @param pitch       音调
     * @param bgsound     背景音编号
     */
    function landingCall($to, $mediaName, $mediaTxt, $displayNum, $playTimes, $respUrl, $userData, $maxCallTime, $speed, $volume, $pitch, $bgsound) {
        //调用外呼通知接口
        echo "Try to make a landingcall,called is $to <br/>";
        $result = $this->SMS_SDK_REST->landingCall($to, $mediaName, $mediaTxt, $displayNum, $playTimes, $respUrl, $userData, $maxCallTime, $speed, $volume, $pitch, $bgsound);
        if ($result == NULL) {
            throw new PhalApi_Exception_BadRequest(T("Error SMS_SDK_REST"));
        }
        if ($this->debug) {
            $this->showarr($result);
        }
        return $result;
    }
    /**
     * IVR外呼
     *
     * @param number   待呼叫号码,为Dial节点的属性
     * @param userdata 用户数据,在<startservice>通知中返回,只允许填写数字字符,为Dial节点的属性
     * @param record   是否录音,可填项为true和false,默认值为false不录音,为Dial节点的属性
     */
    function ivrDial($number, $userdata, $record) {
        // 调用IVR外呼接口
        $result = $this->SMS_SDK_REST->ivrDial($number, $userdata, $record);
        if ($result == NULL) {
            throw new PhalApi_Exception_BadRequest(T("Error SMS_SDK_REST"));
        }
        if ($this->debug) {
            $this->showarr($result);
        }
        return $result;
    }
    /**
     * 话单下载
     *
     * @param date       day 代表前一天的数据(从00:00 – 23:59)
     * @param keywords   客户的查询条件,由客户自行定义并提供给云通讯平台。默认不填忽略此参数
     */
    function billRecords($date, $keywords) {
        // 调用话单下载接口
        $result = $this->SMS_SDK_REST->billRecords($date, $keywords);
        if ($result == NULL) {
            throw new PhalApi_Exception_BadRequest(T("Error SMS_SDK_REST"));
        }
        if ($this->debug) {
            $this->showarr($result);
        }
        return $result;
    }
    /**
     * 数组对象取值相关 - 避免出错
     */
    public function getIndex($arr, $key, $default = '') {
        return isset($arr[$key]) ? $arr[$key] : $default;
    }
    /**
     * 直接显示内容数组
     */
    public function showarr($a) {
        echo('<pre>');
        print_r($a);
        echo('</pre>');
    }
}
Library/SMS/README.md
New file
@@ -0,0 +1,81 @@
#PhalApi-SMS基于PhalApi容联云短信服务器拓展
![](http://webtools.qiniudn.com/master-LOGO-20150410_50.jpg)
##前言
在做项目时更换短信运营商时,找到了容联云通讯(滴滴用的是他的服务),感觉很不错看了下SDK文件和测试Demo感觉使用起来并不是很方便,
因为确实很多项目都会用到这一套服务比较希望好用优雅一些,所以提供了本次拓展也希望大家喜欢
附上:
官网地址:[http://www.phalapi.net/](http://www.phalapi.net/ "PhalApi官网")
开源中国Git地址:[http://git.oschina.net/dogstar/PhalApi/tree/release](http://git.oschina.net/dogstar/PhalApi/tree/release "开源中国Git地址")
开源中国拓展Git地址:[http://git.oschina.net/dogstar/PhalApi-Library](http://git.oschina.net/dogstar/PhalApi-Library "开源中国Git地址")
##1. 安装
配置方式非常简单只需要把拓展下载下来放入Library文件内即可,然后就可以使用如下方法进行实例
    //初始化传入配置文件地址
    $SMS = new SMS_Lite("app.SMSService");
    //初始化并且打开调试模式
    $SMS = new SMS_Lite("app.SMSService",true);
在调试模式下返回信息会被打印出来(建议在生产环境不要开启)
##2.配置
配置文件约定存放在app.SMSService,serverPort以及serverIP不进行配置为默认环境
    "SMSService" => array(
        "accountSid"   => "",  //主帐号
        "accountToken" => "",  //主帐号Token
        "appId"        => "",  //应用Id
        "serverPort"   => "",  //请求端口 默认:8883
        "serverIP"     => ""   //请求地址不需要写https:// 默认:sandboxapp.cloopen.com 测试环境
    )
##3. SDK-API
通过如上配置都可以开始进行正常的使用了如下
    //发送模板短信
    $SMS->sendTemplateSMS("手机号码", "内容数据", "模板Id");
    //短信模板查询
    $SMS->QuerySMSTemplate("模板ID");
    //语音验证码
    $SMS->voiceVerify("验证码内容", "循环播放次数", "接收号码", "显示的主叫号码", "营销外呼状态通知回调地址", '语言类型', '第三方私有数据');
    //语音文件上传
    $SMS->MediaFileUpload("文件名", "文件二进制数据");
    //话单下载 前一天的数据(从00:00 – 23:59)
    $SMS->billRecords("话单规则", "客户的查询条件");
    //IVR外呼
    $SMS->ivrDial("待呼叫号码", "用户数据", "是否录音");
    //外呼通知
    $SMS->landingCall("被叫号码", "语音文件名称", "文本内容", "显示的主叫号码", "循环播放次数", "外呼通知状态通知回调地址", '用户私有数据', '最大通话时长', '发音速度', '音量', '音调', '背景音编号');
    //主帐号信息查询
    $SMS->queryAccountInfo();
    //呼叫状态查询
    $SMS->QueryCallState("callid", "查询结果通知的回调url地址");
##4. 总结
希望此拓展能够给大家带来方便以及实用,暂时只支持容联云如有其他童鞋希望能加入其余常用运营商可与笔者进行联系!
注:笔者能力有限有说的不对的地方希望大家能够指出,也希望多多交流!
**官网QQ交流群:421032344  欢迎大家的加入!**
Library/SMS/SDK/REST.php
New file
@@ -0,0 +1,1042 @@
<?php
/*
 *  Copyright (c) 2014 The CCP project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a Beijing Speedtong Information Technology Co.,Ltd license
 *  that can be found in the LICENSE file in the root of the web site.
 *
 *   http://www.yuntongxun.com
 *
 *  An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */
class SMS_SDK_REST {
    private $AccountSid;
    private $AccountToken;
    private $AppId;
    private $SubAccountSid;
    private $SubAccountToken;
    private $VoIPAccount;
    private $VoIPPassword;
    private $ServerIP;
    private $ServerPort;
    private $SoftVersion;
    private $Batch;  //时间sh
    private $BodyType = "xml";//包体格式,可填值:json 、xml
    private $enabeLog = true; //日志开关。可填值:true、
    private $Filename = "../log.txt"; //日志文件
    private $Handle;
    function __construct($ServerIP, $ServerPort, $SoftVersion) {
        $this->Batch       = date("YmdHis");
        $this->ServerIP    = $ServerIP;
        $this->ServerPort  = $ServerPort;
        $this->SoftVersion = $SoftVersion;
        $this->Handle      = fopen($this->Filename, 'a');
    }
    /**
     * 设置主帐号
     *
     * @param AccountSid   主帐号
     * @param AccountToken 主帐号Token
     */
    function setAccount($AccountSid, $AccountToken) {
        $this->AccountSid   = $AccountSid;
        $this->AccountToken = $AccountToken;
    }
    /**
     * 设置子帐号
     *
     * @param SubAccountSid   子帐号
     * @param SubAccountToken 子帐号Token
     * @param VoIPAccount     VoIP帐号
     * @param VoIPPassword    VoIP密码
     */
    function setSubAccount($SubAccountSid, $SubAccountToken, $VoIPAccount, $VoIPPassword) {
        $this->SubAccountSid   = $SubAccountSid;
        $this->SubAccountToken = $SubAccountToken;
        $this->VoIPAccount     = $VoIPAccount;
        $this->VoIPPassword    = $VoIPPassword;
    }
    /**
     * 设置应用ID
     *
     * @param AppId 应用ID
     */
    function setAppId($AppId) {
        $this->AppId = $AppId;
    }
    /**
     * 打印日志
     *
     * @param log 日志内容
     */
    function showlog($log) {
        if ($this->enabeLog) {
            fwrite($this->Handle, $log . "\n");
        }
    }
    /**
     * 发起HTTPS请求
     */
    function curl_post($url, $data, $header, $post = 1) {
        //初始化curl
        $ch = curl_init();
        //参数设置
        $res = curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_POST, $post);
        if ($post) {
            curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        }
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        $result = curl_exec($ch);
        //连接失败
        if ($result == FALSE) {
            if ($this->BodyType == 'json') {
                $result = "{\"statusCode\":\"172001\",\"statusMsg\":\"网络错误\"}";
            } else {
                $result = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><Response><statusCode>172001</statusCode><statusMsg>网络错误</statusMsg></Response>";
            }
        }
        curl_close($ch);
        return $result;
    }
    /**
     * 创建子帐号
     *
     * @param friendlyName 子帐号名称
     */
    function createSubAccount($friendlyName) {
        //主帐号鉴权信息验证,对必选参数进行判空。
        $auth = $this->accAuth();
        if ($auth != "") {
            return $auth;
        }
        // 拼接请求包体
        if ($this->BodyType == "json") {
            $body = "{'appId':'$this->AppId','friendlyName':'$friendlyName'}";
        } else {
            $body = "<SubAccount>
                    <appId>$this->AppId</appId>
                    <friendlyName>$friendlyName</friendlyName>
                  </SubAccount>";
        }
        $this->showlog("request body = " . $body);
        // 大写的sig参数
        $sig = strtoupper(md5($this->AccountSid . $this->AccountToken . $this->Batch));
        // 生成请求URL
        $url = "https://$this->ServerIP:$this->ServerPort/$this->SoftVersion/Accounts/$this->AccountSid/SubAccounts?sig=$sig";
        $this->showlog("request url = " . $url);
        // 生成授权:主帐号Id + 英文冒号 + 时间戳
        $authen = base64_encode($this->AccountSid . ":" . $this->Batch);
        // 生成包头
        $header = array(
            "Accept:application/$this->BodyType",
            "Content-Type:application/$this->BodyType;charset=utf-8",
            "Authorization:$authen"
        );
        // 发请求
        $result = $this->curl_post($url, $body, $header);
        $this->showlog("response body = " . $result);
        if ($this->BodyType == "json") {//JSON格式
            $datas = json_decode($result);
        } else { //xml格式
            $datas = simplexml_load_string(trim($result, " \t\n\r"));
        }
        //  if($datas == FALSE){
        //            $datas = new stdClass();
        //            $datas->statusCode = '172003';
        //            $datas->statusMsg = '返回包体错误';
        //        }
        return $datas;
    }
    /**
     * 获取子帐号
     *
     * @param startNo 开始的序号,默认从0开始
     * @param offset  一次查询的最大条数,最小是1条,最大是100条
     */
    function getSubAccounts($startNo, $offset) {
        //主帐号鉴权信息验证,对必选参数进行判空。
        $auth = $this->accAuth();
        if ($auth != "") {
            return $auth;
        }
        // 拼接请求包体
        $body = "
            <SubAccount>
              <appId>$this->AppId</appId>
              <startNo>$startNo</startNo>
              <offset>$offset</offset>
            </SubAccount>";
        if ($this->BodyType == "json") {
            $body = "{'appId':'$this->AppId','startNo':'$startNo','offset':'$offset'}";
        } else {
            $body = "
            <SubAccount>
              <appId>$this->AppId</appId>
              <startNo>$startNo</startNo>
              <offset>$offset</offset>
            </SubAccount>";
        }
        $this->showlog("request body = " . $body);
        // 大写的sig参数
        $sig = strtoupper(md5($this->AccountSid . $this->AccountToken . $this->Batch));
        // 生成请求URL
        $url = "https://$this->ServerIP:$this->ServerPort/$this->SoftVersion/Accounts/$this->AccountSid/GetSubAccounts?sig=$sig";
        $this->showlog("request url = " . $url);
        // 生成授权:主帐户Id + 英文冒号 + 时间戳。
        $authen = base64_encode($this->AccountSid . ":" . $this->Batch);
        // 生成包头
        $header = array(
            "Accept:application/$this->BodyType",
            "Content-Type:application/$this->BodyType;charset=utf-8",
            "Authorization:$authen"
        );
        // 发送请求
        $result = $this->curl_post($url, $body, $header);
        $this->showlog("response body = " . $result);
        if ($this->BodyType == "json") {//JSON格式
            $datas = json_decode($result);
        } else { //xml格式
            $datas = simplexml_load_string(trim($result, " \t\n\r"));
        }
        //  if($datas == FALSE){
        //            $datas = new stdClass();
        //            $datas->statusCode = '172003';
        //            $datas->statusMsg = '返回包体错误';
        //        }
        return $datas;
    }
    /**
     * 子帐号信息查询
     *
     * @param friendlyName 子帐号名称
     */
    function querySubAccount($friendlyName) {
        //主帐号鉴权信息验证,对必选参数进行判空。
        $auth = $this->accAuth();
        if ($auth != "") {
            return $auth;
        }
        // 拼接请求包体
        if ($this->BodyType == "json") {
            $body = "{'appId':'$this->AppId','friendlyName':'$friendlyName'}";
        } else {
            $body = "
            <SubAccount>
              <appId>$this->AppId</appId>
              <friendlyName>$friendlyName</friendlyName>
            </SubAccount>";
        }
        $this->showlog("request body = " . $body);
        // 大写的sig参数
        $sig = strtoupper(md5($this->AccountSid . $this->AccountToken . $this->Batch));
        // 生成请求URL
        $url = "https://$this->ServerIP:$this->ServerPort/$this->SoftVersion/Accounts/$this->AccountSid/QuerySubAccountByName?sig=$sig";
        $this->showlog("request url = " . $url);
        // 生成授权:主帐户Id + 英文冒号 + 时间戳。
        $authen = base64_encode($this->AccountSid . ":" . $this->Batch);
        // 生成包头
        $header = array(
            "Accept:application/$this->BodyType",
            "Content-Type:application/$this->BodyType;charset=utf-8",
            "Authorization:$authen"
        );
        // 发送请求
        $result = $this->curl_post($url, $body, $header);
        $this->showlog("response body = " . $result);
        if ($this->BodyType == "json") {//JSON格式
            $datas = json_decode($result);
        } else { //xml格式
            $datas = simplexml_load_string(trim($result, " \t\n\r"));
        }
        //  if($datas == FALSE){
        //            $datas = new stdClass();
        //            $datas->statusCode = '172003';
        //            $datas->statusMsg = '返回包体错误';
        //        }
        return $datas;
    }
    /**
     * 发送模板短信
     *
     * @param to      短信接收彿手机号码集合,用英文逗号分开
     * @param datas   内容数据
     * @param $tempId 模板Id
     */
    function sendTemplateSMS($to, $datas, $tempId) {
        //主帐号鉴权信息验证,对必选参数进行判空。
        $auth = $this->accAuth();
        if ($auth != "") {
            return $auth;
        }
        // 拼接请求包体
        if ($this->BodyType == "json") {
            $data = "";
            for ($i = 0; $i < count($datas); $i++) {
                $data = $data . "'" . $datas[$i] . "',";
            }
            $body = "{'to':'$to','templateId':'$tempId','appId':'$this->AppId','datas':[" . $data . "]}";
        } else {
            $data = "";
            for ($i = 0; $i < count($datas); $i++) {
                $data = $data . "<data>" . $datas[$i] . "</data>";
            }
            $body = "<TemplateSMS>
                    <to>$to</to>
                    <appId>$this->AppId</appId>
                    <templateId>$tempId</templateId>
                    <datas>" . $data . "</datas>
                  </TemplateSMS>";
        }
        $this->showlog("request body = " . $body);
        // 大写的sig参数
        $sig = strtoupper(md5($this->AccountSid . $this->AccountToken . $this->Batch));
        // 生成请求URL
        $url = "https://$this->ServerIP:$this->ServerPort/$this->SoftVersion/Accounts/$this->AccountSid/SMS/TemplateSMS?sig=$sig";
        $this->showlog("request url = " . $url);
        // 生成授权:主帐户Id + 英文冒号 + 时间戳。
        $authen = base64_encode($this->AccountSid . ":" . $this->Batch);
        // 生成包头
        $header = array(
            "Accept:application/$this->BodyType",
            "Content-Type:application/$this->BodyType;charset=utf-8",
            "Authorization:$authen"
        );
        // 发送请求
        $result = $this->curl_post($url, $body, $header);
        $this->showlog("response body = " . $result);
        if ($this->BodyType == "json") {//JSON格式
            $datas = json_decode($result);
        } else { //xml格式
            $datas = simplexml_load_string(trim($result, " \t\n\r"));
        }
        //  if($datas == FALSE){
        //            $datas = new stdClass();
        //            $datas->statusCode = '172003';
        //            $datas->statusMsg = '返回包体错误';
        //        }
        //重新装填数据
        if ($datas->statusCode == 0) {
            if ($this->BodyType == "json") {
                $datas->TemplateSMS = $datas->templateSMS;
                unset($datas->templateSMS);
            }
        }
        return $datas;
    }
    /**
     * 双向回呼
     *
     * @param from            主叫电话号码
     * @param to              被叫电话号码
     * @param customerSerNum  被叫侧显示的客服号码
     * @param fromSerNum      主叫侧显示的号码
     * @param promptTone      自定义回拨提示音
     * @param userData        第三方私有数据
     * @param maxCallTime     最大通话时长
     * @param hangupCdrUrl    实时话单通知地址
     * @param alwaysPlay      是否一直播放提示音
     * @param terminalDtmf    用于终止播放promptTone参数定义的提示音
     * @param needBothCdr     是否给主被叫发送话单
     * @param needRecord      是否录音
     * @param countDownTime   设置倒计时时间
     * @param countDownPrompt 倒计时时间到后播放的提示音
     */
    function callBack($from, $to, $customerSerNum, $fromSerNum, $promptTone, $alwaysPlay, $terminalDtmf, $userData, $maxCallTime, $hangupCdrUrl, $needBothCdr, $needRecord, $countDownTime, $countDownPrompt) {
        //子帐号鉴权信息验证,对必选参数进行判空。
        $auth = $this->subAuth();
        if ($auth != "") {
            return $auth;
        }
        // 拼接请求包体
        if ($this->BodyType == "json") {
            $body = "{'from':'$from','to':'$to','customerSerNum':'$customerSerNum','fromSerNum':'$fromSerNum','promptTone':'$promptTone','userData':'$userData','maxCallTime':'$maxCallTime','hangupCdrUrl':'$hangupCdrUrl',
           'alwaysPlay':'$alwaysPlay','terminalDtmf':'$terminalDtmf','needBothCdr':'$needBothCdr',
           'needRecord':'$needRecord','countDownTime':'$$countDownTime','countDownPrompt':'$countDownPrompt'}";
        } else {
            $body = "<CallBack>
                     <from>$from</from>
                     <to>$to</to>
                     <customerSerNum>$customerSerNum</customerSerNum>
                     <fromSerNum>$fromSerNum</fromSerNum>
                     <promptTone>$promptTone</promptTone>
                               <userData>$userData</userData>
                               <maxCallTime>$maxCallTime</maxCallTime>
                               <hangupCdrUrl>$hangupCdrUrl</hangupCdrUrl>
                     <alwaysPlay>$alwaysPlay</alwaysPlay>
                     <terminalDtmf>$terminalDtmf</terminalDtmf>
                     <needBothCdr>$needBothCdr</needBothCdr>
                     <needRecord>$needRecord</needRecord>
                     <countDownTime>$countDownTime</countDownTime>
                     <countDownPrompt>$countDownPrompt</countDownPrompt>
                   </CallBack>";
        }
        $this->showlog("request body = " . $body);
        // 大写的sig参数
        $sig = strtoupper(md5($this->SubAccountSid . $this->SubAccountToken . $this->Batch));
        // 生成请求URL
        $url = "https://$this->ServerIP:$this->ServerPort/$this->SoftVersion/SubAccounts/$this->SubAccountSid/Calls/Callback?sig=$sig";
        $this->showlog("request url = " . $url);
        // 生成授权:子帐号Id + 英文冒号 + 时间戳
        $authen = base64_encode($this->SubAccountSid . ":" . $this->Batch);
        // 生成包头
        $header = array(
            "Accept:application/$this->BodyType",
            "Content-Type:application/$this->BodyType;charset=utf-8",
            "Authorization:$authen"
        );
        // 发请求
        $result = $this->curl_post($url, $body, $header);
        $this->showlog("response body = " . $result);
        if ($this->BodyType == "json") {//JSON格式
            $datas = json_decode($result);
        } else { //xml格式
            $datas = simplexml_load_string(trim($result, " \t\n\r"));
        }
        //  if($datas == FALSE){
        //            $datas = new stdClass();
        //            $datas->statusCode = '172003';
        //            $datas->statusMsg = '返回包体错误';
        //        }
        return $datas;
    }
    /**
     * 外呼通知
     *
     * @param to          被叫号码
     * @param mediaName   语音文件名称,格式 wav。与mediaTxt不能同时为空。当不为空时mediaTxt属性失效。
     * @param mediaTxt    文本内容
     * @param displayNum  显示的主叫号码
     * @param playTimes   循环播放次数,1-3次,默认播放1次。
     * @param respUrl     外呼通知状态通知回调地址,云通讯平台将向该Url地址发送呼叫结果通知。
     * @param userData    用户私有数据
     * @param maxCallTime 最大通话时长
     * @param speed       发音速度
     * @param volume      音量
     * @param pitch       音调
     * @param bgsound     背景音编号
     */
    function landingCall($to, $mediaName, $mediaTxt, $displayNum, $playTimes, $respUrl, $userData, $maxCallTime, $speed, $volume, $pitch, $bgsound) {
        //主帐号鉴权信息验证,对必选参数进行判空。
        $auth = $this->accAuth();
        if ($auth != "") {
            return $auth;
        }
        // 拼接请求包体
        if ($this->BodyType == "json") {
            $body = "{'playTimes':'$playTimes','mediaTxt':'$mediaTxt','mediaName':'$mediaName','to':'$to','appId':'$this->AppId','displayNum':'$displayNum','respUrl':'$respUrl',
           'userData':'$userData','maxCallTime':'$maxCallTime','speed':'$speed','volume':'$volume','pitch':'$pitch','bgsound':'$bgsound'}";
        } else {
            $body = "<LandingCall>
                    <to>$to</to>
                    <mediaName>$mediaName</mediaName>
                    <mediaTxt>$mediaTxt</mediaTxt>
                    <appId>$this->AppId</appId>
                    <displayNum>$displayNum</displayNum>
                    <playTimes>$playTimes</playTimes>
                    <respUrl>$respUrl</respUrl>
                    <userData>$userData</userData>
                    <maxCallTime>$maxCallTime</maxCallTime>
                    <speed>$speed</speed>
                    <volume>$volume</volume>
                    <pitch>$pitch</pitch>
                    <bgsound>$bgsound</bgsound>
                  </LandingCall>";
        }
        $this->showlog("request body = " . $body);
        // 大写的sig参数
        $sig = strtoupper(md5($this->AccountSid . $this->AccountToken . $this->Batch));
        // 生成请求URL
        $url = "https://$this->ServerIP:$this->ServerPort/$this->SoftVersion/Accounts/$this->AccountSid/Calls/LandingCalls?sig=$sig";
        $this->showlog("request url = " . $url);
        // 生成授权:主帐户Id + 英文冒号 + 时间戳。
        $authen = base64_encode($this->AccountSid . ":" . $this->Batch);
        // 生成包头
        $header = array(
            "Accept:application/$this->BodyType",
            "Content-Type:application/$this->BodyType;charset=utf-8",
            "Authorization:$authen"
        );
        // 发送请求
        $result = $this->curl_post($url, $body, $header);
        $this->showlog("response body = " . $result);
        if ($this->BodyType == "json") {//JSON格式
            $datas = json_decode($result);
        } else { //xml格式
            $datas = simplexml_load_string(trim($result, " \t\n\r"));
        }
        //  if($datas == FALSE){
        //            $datas = new stdClass();
        //            $datas->statusCode = '172003';
        //            $datas->statusMsg = '返回包体错误';
        //        }
        return $datas;
    }
    /**
     * 语音验证码
     *
     * @param verifyCode 验证码内容,为数字和英文字母,不区分大小写,长度4-8位
     * @param playTimes  播放次数,1-3次
     * @param to         接收号码
     * @param displayNum 显示的主叫号码
     * @param respUrl    语音验证码状态通知回调地址,云通讯平台将向该Url地址发送呼叫结果通知
     * @param lang       语言类型
     * @param userData   第三方私有数据
     */
    function voiceVerify($verifyCode, $playTimes, $to, $displayNum, $respUrl, $lang, $userData) {
        //主帐号鉴权信息验证,对必选参数进行判空。
        $auth = $this->accAuth();
        if ($auth != "") {
            return $auth;
        }
        // 拼接请求包体
        if ($this->BodyType == "json") {
            $body = "{'appId':'$this->AppId','verifyCode':'$verifyCode','playTimes':'$playTimes','to':'$to','respUrl':'$respUrl','displayNum':'$displayNum',
           'lang':'$lang','userData':'$userData'}";
        } else {
            $body = "<VoiceVerify>
                    <appId>$this->AppId</appId>
                    <verifyCode>$verifyCode</verifyCode>
                    <playTimes>$playTimes</playTimes>
                    <to>$to</to>
                    <respUrl>$respUrl</respUrl>
                    <displayNum>$displayNum</displayNum>
                    <lang>$lang</lang>
                    <userData>$userData</userData>
                  </VoiceVerify>";
        }
        $this->showlog("request body = " . $body);
        // 大写的sig参数
        $sig = strtoupper(md5($this->AccountSid . $this->AccountToken . $this->Batch));
        // 生成请求URL
        $url = "https://$this->ServerIP:$this->ServerPort/$this->SoftVersion/Accounts/$this->AccountSid/Calls/VoiceVerify?sig=$sig";
        $this->showlog("request url = " . $url);
        // 生成授权:主帐户Id + 英文冒号 + 时间戳。
        $authen = base64_encode($this->AccountSid . ":" . $this->Batch);
        // 生成包头
        $header = array(
            "Accept:application/$this->BodyType",
            "Content-Type:application/$this->BodyType;charset=utf-8",
            "Authorization:$authen"
        );
        // 发送请求
        $result = $this->curl_post($url, $body, $header);
        $this->showlog("response body = " . $result);
        if ($this->BodyType == "json") {//JSON格式
            $datas = json_decode($result);
        } else { //xml格式
            $datas = simplexml_load_string(trim($result, " \t\n\r"));
        }
        //  if($datas == FALSE){
        //            $datas = new stdClass();
        //            $datas->statusCode = '172003';
        //            $datas->statusMsg = '返回包体错误';
        //        }
        return $datas;
    }
    /**
     * IVR外呼
     *
     * @param number   待呼叫号码,为Dial节点的属性
     * @param userdata 用户数据,在<startservice>通知中返回,只允许填写数字字符,为Dial节点的属性
     * @param record   是否录音,可填项为true和false,默认值为false不录音,为Dial节点的属性
     */
    function ivrDial($number, $userdata, $record) {
        //主帐号鉴权信息验证,对必选参数进行判空。
        $auth = $this->accAuth();
        if ($auth != "") {
            return $auth;
        }
        // 拼接请求包体
        $body = " <Request>
                  <Appid>$this->AppId</Appid>
                  <Dial number='$number'  userdata='$userdata' record='$record'></Dial>
                </Request>";
        $this->showlog("request body = " . $body);
        // 大写的sig参数
        $sig = strtoupper(md5($this->AccountSid . $this->AccountToken . $this->Batch));
        // 生成请求URL
        $url = "https://$this->ServerIP:$this->ServerPort/$this->SoftVersion/Accounts/$this->AccountSid/ivr/dial?sig=$sig";
        $this->showlog("request url = " . $url);
        // 生成授权:主帐户Id + 英文冒号 + 时间戳。
        $authen = base64_encode($this->AccountSid . ":" . $this->Batch);
        // 生成包头
        $header = array(
            "Accept:application/xml",
            "Content-Type:application/xml;charset=utf-8",
            "Authorization:$authen"
        );
        // 发送请求
        $result = $this->curl_post($url, $body, $header);
        $this->showlog("response body = " . $result);
        $datas = simplexml_load_string(trim($result, " \t\n\r"));
        //  if($datas == FALSE){
        //            $datas = new stdClass();
        //            $datas->statusCode = '172003';
        //            $datas->statusMsg = '返回包体错误';
        //        }
        return $datas;
    }
    /**
     * 话单下载
     *
     * @param date       day 代表前一天的数据(从00:00 – 23:59)
     * @param keywords   客户的查询条件,由客户自行定义并提供给云通讯平台。默认不填忽略此参数
     */
    function billRecords($date, $keywords) {
        //主帐号鉴权信息验证,对必选参数进行判空。
        $auth = $this->accAuth();
        if ($auth != "") {
            return $auth;
        }
        // 拼接请求包体
        if ($this->BodyType == "json") {
            $body = "{'appId':'$this->AppId','date':'$date','keywords':'$keywords'}";
        } else {
            $body = "<BillRecords>
                    <appId>$this->AppId</appId>
                    <date>$date</date>
                    <keywords>$keywords</keywords>
                  </BillRecords>";
        }
        $this->showlog("request body = " . $body);
        // 大写的sig参数
        $sig = strtoupper(md5($this->AccountSid . $this->AccountToken . $this->Batch));
        // 生成请求URL
        $url = "https://$this->ServerIP:$this->ServerPort/$this->SoftVersion/Accounts/$this->AccountSid/BillRecords?sig=$sig";
        $this->showlog("request url = " . $url);
        // 生成授权:主帐户Id + 英文冒号 + 时间戳。
        $authen = base64_encode($this->AccountSid . ":" . $this->Batch);
        // 生成包头
        $header = array(
            "Accept:application/$this->BodyType",
            "Content-Type:application/$this->BodyType;charset=utf-8",
            "Authorization:$authen"
        );
        // 发送请求
        $result = $this->curl_post($url, $body, $header);
        $this->showlog("response body = " . $result);
        if ($this->BodyType == "json") {//JSON格式
            $datas = json_decode($result);
        } else { //xml格式
            $datas = simplexml_load_string(trim($result, " \t\n\r"));
        }
        //  if($datas == FALSE){
        //            $datas = new stdClass();
        //            $datas->statusCode = '172003';
        //            $datas->statusMsg = '返回包体错误';
        //        }
        return $datas;
    }
    /**
     * 主帐号信息查询
     */
    function queryAccountInfo() {
        //主帐号鉴权信息验证,对必选参数进行判空。
        $auth = $this->accAuth();
        if ($auth != "") {
            return $auth;
        }
        // 大写的sig参数
        $sig = strtoupper(md5($this->AccountSid . $this->AccountToken . $this->Batch));
        // 生成请求URL
        $url = "https://$this->ServerIP:$this->ServerPort/$this->SoftVersion/Accounts/$this->AccountSid/AccountInfo?sig=$sig";
        $this->showlog("request url = " . $url);
        // 生成授权:主帐户Id + 英文冒号 + 时间戳。
        $authen = base64_encode($this->AccountSid . ":" . $this->Batch);
        // 生成包头
        $header = array(
            "Accept:application/$this->BodyType",
            "Content-Type:application/$this->BodyType;charset=utf-8",
            "Authorization:$authen"
        );
        // 发送请求
        $result = $this->curl_post($url, "", $header, 0);
        $this->showlog("response body = " . $result);
        if ($this->BodyType == "json") {//JSON格式
            $datas = json_decode($result);
        } else { //xml格式
            $datas = simplexml_load_string(trim($result, " \t\n\r"));
        }
        //  if($datas == FALSE){
        //            $datas = new stdClass();
        //            $datas->statusCode = '172003';
        //            $datas->statusMsg = '返回包体错误';
        //        }
        return $datas;
    }
    /**
     * 短信模板查询
     *
     * @param date     templateId 模板ID
     */
    function QuerySMSTemplate($templateId) {
        //主帐号鉴权信息验证,对必选参数进行判空。
        $auth = $this->accAuth();
        if ($auth != "") {
            return $auth;
        }
        // 拼接请求包体
        if ($this->BodyType == "json") {
            $body = "{'appId':'$this->AppId','templateId':'$templateId'}";
        } else {
            $body = "<Request>
                    <appId>$this->AppId</appId>
                    <templateId>$templateId</templateId>
                  </Request>";
        }
        $this->showlog("request body = " . $body);
        // 大写的sig参数
        $sig = strtoupper(md5($this->AccountSid . $this->AccountToken . $this->Batch));
        // 生成请求URL
        $url = "https://$this->ServerIP:$this->ServerPort/$this->SoftVersion/Accounts/$this->AccountSid/SMS/QuerySMSTemplate?sig=$sig";
        $this->showlog("request url = " . $url);
        // 生成授权:主帐户Id + 英文冒号 + 时间戳。
        $authen = base64_encode($this->AccountSid . ":" . $this->Batch);
        // 生成包头
        $header = array(
            "Accept:application/$this->BodyType",
            "Content-Type:application/$this->BodyType;charset=utf-8",
            "Authorization:$authen"
        );
        // 发送请求
        $result = $this->curl_post($url, $body, $header);
        $this->showlog("response body = " . $result);
        if ($this->BodyType == "json") {//JSON格式
            $datas = json_decode($result);
        } else { //xml格式
            $datas = simplexml_load_string(trim($result, " \t\n\r"));
        }
        //  if($datas == FALSE){
        //            $datas = new stdClass();
        //            $datas->statusCode = '172003';
        //            $datas->statusMsg = '返回包体错误';
        //        }
        return $datas;
    }
    /**
     * 取消回拨
     *
     * @param callSid          一个由32个字符组成的电话唯一标识符
     * @param type             0: 任意时间都可以挂断电话;1 :被叫应答前可以挂断电话,其他时段返回错误代码;2: 主叫应答前可以挂断电话,其他时段返回错误代码;默认值为0。
     */
    function CallCancel($callSid, $type) {
        //主帐号鉴权信息验证,对必选参数进行判空。
        $auth = $this->subAuth();
        if ($auth != "") {
            return $auth;
        }
        // 拼接请求包体
        if ($this->BodyType == "json") {
            $body = "{'appId':'$this->AppId','callSid':'$callSid','type':'$type'}";
        } else {
            $body = "<CallCancel>
                    <appId>$this->AppId</appId>
                    <callSid>$callSid</callSid>
                    <type>$type</type>
                  </CallCancel>";
        }
        $this->showlog("request body = " . $body);
        // 大写的sig参数
        $sig = strtoupper(md5($this->SubAccountSid . $this->SubAccountToken . $this->Batch));
        // 生成请求URL
        $url = "https://$this->ServerIP:$this->ServerPort/$this->SoftVersion/SubAccounts/$this->SubAccountSid/Calls/CallCancel?sig=$sig";
        $this->showlog("request url = " . $url);
        // 生成授权:主帐户Id + 英文冒号 + 时间戳。
        $authen = base64_encode($this->SubAccountSid . ":" . $this->Batch);
        // 生成包头
        $header = array(
            "Accept:application/$this->BodyType",
            "Content-Type:application/$this->BodyType;charset=utf-8",
            "Authorization:$authen"
        );
        // 发送请求
        $result = $this->curl_post($url, $body, $header);
        $this->showlog("response body = " . $result);
        if ($this->BodyType == "json") {//JSON格式
            $datas = json_decode($result);
        } else { //xml格式
            $datas = simplexml_load_string(trim($result, " \t\n\r"));
        }
        //  if($datas == FALSE){
        //            $datas = new stdClass();
        //            $datas->statusCode = '172003';
        //            $datas->statusMsg = '返回包体错误';
        //        }
        return $datas;
    }
    /**
     * 呼叫状态查询
     *
     * @param callid     呼叫Id
     * @param action     查询结果通知的回调url地址
     */
    function QueryCallState($callid, $action) {
        //主帐号鉴权信息验证,对必选参数进行判空。
        $auth = $this->accAuth();
        if ($auth != "") {
            return $auth;
        }
        // 拼接请求包体
        if ($this->BodyType == "json") {
            $body = "{'Appid':'$this->AppId','QueryCallState':{'callid':'$callid','action':'$action'}}";
        } else {
            $body = "<Request>
                    <Appid>$this->AppId</Appid>
                    <QueryCallState callid ='$callid' action='$action'/>
                  </Request>";
        }
        $this->showlog("request body = " . $body);
        // 大写的sig参数
        $sig = strtoupper(md5($this->AccountSid . $this->AccountToken . $this->Batch));
        // 生成请求URL
        $url = "https://$this->ServerIP:$this->ServerPort/$this->SoftVersion/Accounts/$this->AccountSid/ivr/call?sig=$sig&callid=$callid";
        $this->showlog("request url = " . $url);
        // 生成授权:主帐户Id + 英文冒号 + 时间戳。
        $authen = base64_encode($this->AccountSid . ":" . $this->Batch);
        // 生成包头
        $header = array(
            "Accept:application/$this->BodyType",
            "Content-Type:application/$this->BodyType;charset=utf-8",
            "Authorization:$authen"
        );
        // 发送请求
        $result = $this->curl_post($url, $body, $header);
        $this->showlog("response body = " . $result);
        if ($this->BodyType == "json") {//JSON格式
            $datas = json_decode($result);
        } else { //xml格式
            $datas = simplexml_load_string(trim($result, " \t\n\r"));
        }
        //  if($datas == FALSE){
        //            $datas = new stdClass();
        //            $datas->statusCode = '172003';
        //            $datas->statusMsg = '返回包体错误';
        //        }
        return $datas;
    }
    /**
     * 呼叫结果查询
     *
     * @param callSid     呼叫Id
     */
    function CallResult($callSid) {
        //主帐号鉴权信息验证,对必选参数进行判空。
        $auth = $this->accAuth();
        if ($auth != "") {
            return $auth;
        }
        // 大写的sig参数
        $sig = strtoupper(md5($this->AccountSid . $this->AccountToken . $this->Batch));
        // 生成请求URL
        $url = "https://$this->ServerIP:$this->ServerPort/$this->SoftVersion/Accounts/$this->AccountSid/CallResult?sig=$sig&callsid=$callSid";
        $this->showlog("request url = " . $url);
        // 生成授权:主帐户Id + 英文冒号 + 时间戳。
        $authen = base64_encode($this->AccountSid . ":" . $this->Batch);
        // 生成包头
        $header = array(
            "Accept:application/$this->BodyType",
            "Content-Type:application/$this->BodyType;charset=utf-8",
            "Authorization:$authen"
        );
        // 发送请求
        $result = $this->curl_post($url, "", $header, 0);
        $this->showlog("response body = " . $result);
        if ($this->BodyType == "json") {//JSON格式
            $datas = json_decode($result);
        } else { //xml格式
            $datas = simplexml_load_string(trim($result, " \t\n\r"));
        }
        //  if($datas == FALSE){
        //            $datas = new stdClass();
        //            $datas->statusCode = '172003';
        //            $datas->statusMsg = '返回包体错误';
        //        }
        return $datas;
    }
    /**
     * 语音文件上传
     *
     * @param filename     文件名
     * @param body         二进制串
     */
    function MediaFileUpload($filename, $body) {
        //主帐号鉴权信息验证,对必选参数进行判空。
        $auth = $this->accAuth();
        if ($auth != "") {
            return $auth;
        }
        // 拼接请求包体
        $this->showlog("request body = " . $body);
        // 大写的sig参数
        $sig = strtoupper(md5($this->AccountSid . $this->AccountToken . $this->Batch));
        // 生成请求URL
        $url = "https://$this->ServerIP:$this->ServerPort/$this->SoftVersion/Accounts/$this->AccountSid/Calls/MediaFileUpload?sig=$sig&appid=$this->AppId&filename=$filename";
        $this->showlog("request url = " . $url);
        // 生成授权:主帐户Id + 英文冒号 + 时间戳。
        $authen = base64_encode($this->AccountSid . ":" . $this->Batch);
        // 生成包头
        $header = array(
            "Accept:application/$this->BodyType",
            "Content-Type:application/octet-stream",
            "Authorization:$authen"
        );
        // 发送请求
        $result = $this->curl_post($url, $body, $header);
        $this->showlog("response body = " . $result);
        if ($this->BodyType == "json") {//JSON格式
            $datas = json_decode($result);
        } else { //xml格式
            $datas = simplexml_load_string(trim($result, " \t\n\r"));
        }
        //  if($datas == FALSE){
        //            $datas = new stdClass();
        //            $datas->statusCode = '172003';
        //            $datas->statusMsg = '返回包体错误';
        //        }
        return $datas;
    }
    /**
     * 子帐号鉴权
     */
    function subAuth() {
        if ($this->ServerIP == "") {
            $data             = new stdClass();
            $data->statusCode = '172004';
            $data->statusMsg  = 'IP为空';
            return $data;
        }
        if ($this->ServerPort <= 0) {
            $data             = new stdClass();
            $data->statusCode = '172005';
            $data->statusMsg  = '端口错误(小于等于0)';
            return $data;
        }
        if ($this->SoftVersion == "") {
            $data             = new stdClass();
            $data->statusCode = '172013';
            $data->statusMsg  = '版本号为空';
            return $data;
        }
        if ($this->SubAccountSid == "") {
            $data             = new stdClass();
            $data->statusCode = '172008';
            $data->statusMsg  = '子帐号为空';
            return $data;
        }
        if ($this->SubAccountToken == "") {
            $data             = new stdClass();
            $data->statusCode = '172009';
            $data->statusMsg  = '子帐号令牌为空';
            return $data;
        }
        if ($this->AppId == "") {
            $data             = new stdClass();
            $data->statusCode = '172012';
            $data->statusMsg  = '应用ID为空';
            return $data;
        }
    }
    /**
     * 主帐号鉴权
     */
    function accAuth() {
        if ($this->ServerIP == "") {
            $data             = new stdClass();
            $data->statusCode = '172004';
            $data->statusMsg  = 'IP为空';
            return $data;
        }
        if ($this->ServerPort <= 0) {
            $data             = new stdClass();
            $data->statusCode = '172005';
            $data->statusMsg  = '端口错误(小于等于0)';
            return $data;
        }
        if ($this->SoftVersion == "") {
            $data             = new stdClass();
            $data->statusCode = '172013';
            $data->statusMsg  = '版本号为空';
            return $data;
        }
        if ($this->AccountSid == "") {
            $data             = new stdClass();
            $data->statusCode = '172006';
            $data->statusMsg  = '主帐号为空';
            return $data;
        }
        if ($this->AccountToken == "") {
            $data             = new stdClass();
            $data->statusCode = '172007';
            $data->statusMsg  = '主帐号令牌为空';
            return $data;
        }
        if ($this->AppId == "") {
            $data             = new stdClass();
            $data->statusCode = '172012';
            $data->statusMsg  = '应用ID为空';
            return $data;
        }
    }
}
?>
PhalApi/PhalApi/Helper/api_desc_tpl.php
@@ -208,12 +208,12 @@
/**
 * 底部
 */
$version = PHALAPI_VERSION;
$version = '孕妇哨';
echo <<<EOT
        <div class="ui blue message">
          <strong>温馨提示:</strong> 此接口参数列表根据后台代码自动生成,可将 ?service= 改成您需要查询的接口/服务
        </div>
        <p>&copy; Powered  By <a href="http://www.phalapi.net/" target="_blank">PhalApi {$version}</a><span id="version_update"></span></p>
        <p>&copy; Powered  By {$version}<span id="version_update"></span></p>
        </div>
    </div>
    <script type="text/javascript">
@@ -251,28 +251,6 @@
            checkLastestVersion();
        })
        // 检测最新版本
        function checkLastestVersion() {
                $.ajax({
                    url:'https://www.phalapi.net/check_lastest_version.php',
                    type:'get',
                    data:{version : '$version'},
                    success:function(res,status,xhr){
                        if (!res.ret || res.ret != 200) {
                            return;
                        }
                        if (res.data.need_upgrade >= 0) {
                            return;
                        }
                        $('#version_update').html('&nbsp; | &nbsp; <a target="_blank" href=" ' + res.data.url + ' "><strong>免费升级到 PhalApi ' + res.data.version + '</strong></a>');
                    },
                    error:function(error){
                        console.log(error)
                    }
                })
        }
    </script>
</body>
</html>
Public/listAllApis.php
New file
@@ -0,0 +1,53 @@
<?php
/**
 * PhalApi在线接口列表文档 - 自动生成
 *
 * - 对Api_系列的接口,进行罗列
 * - 按service进行字典排序
 * - 支持多级目录扫描
 *
 * <br>使用示例:<br>
 * ```
 * <?php
 * // 左侧菜单说明
 * class Api_Demo extends PhalApi_Api {
 *      /**
 *       * 接口服务名称
 *       * @desc 更多说明
 *       * /
 *      public function index() {
 *      }
 * }
 * ```
 * @license     http://www.phalapi.net/license GPL 协议
 * @link        http://www.phalapi.net/
 * @author      xiaoxunzhao     2015-10-25
 * @modify      Aevit           2014-10-29
 * @modify      shwy            2017-03-02
 * @modify      dogstar         2017-06-17
 */
require_once dirname(__FILE__) . '/../init.php';
$projectName = 'PhalApi开源接口框架';
/**
 * 项目的文件夹名
 * TODO: 请根据需要,修改成你的项目名称
 */
$apiDirName = 'Demo';
/**
 * 扩展类库
 * TODO: 请根据需要,添加需要显示的扩展路径,即./Api目录的父路径
 */
$libraryPaths = array(
    'Library/User/User',    // User扩展
    'Library/Auth/Auth',    // Auth扩展
    'Library/Qiniu/CDN',    // 七牛扩展
    'Library/WechatMini/WechatMini', // 微信小程序扩展
);
$apiList = new PhalApi_Helper_ApiList($projectName);
$apiList->render($apiDirName, $libraryPaths);
Public/yfs/checkApiParams.php
New file
@@ -0,0 +1,34 @@
<?php
/**
 * 工具 - 查看接口参数规则
 */
require_once dirname(__FILE__) . '/../init.php';
$projectName = 'PhalApi开源接口框架';
/**
 * TODO: 装载你的接口
 */
DI()->loader->addDirs('Yfs');
/**
 * 扩展类库
 *
 * TODO: 请根据需要,添加需要显示的扩展路径,即./Api目录的父路径
 */
$libraryPaths = array(
    'Library/User/User',    // User扩展
    'Library/Auth/Auth',    // Auth扩展
    'Library/Qiniu/CDN',    // 七牛扩展
    'Library/WechatMini/WechatMini', // 微信小程序扩展
);
foreach ($libraryPaths as $aPath) {
    $toAddDir = str_replace('/', DIRECTORY_SEPARATOR, $aPath);
    DI()->loader->addDirs($toAddDir);
}
$apiDesc = new PhalApi_Helper_ApiDesc($projectName);
$apiDesc->render();
Public/yfs/listAllApis.php
New file
@@ -0,0 +1,53 @@
<?php
/**
 * PhalApi在线接口列表文档 - 自动生成
 *
 * - 对Api_系列的接口,进行罗列
 * - 按service进行字典排序
 * - 支持多级目录扫描
 *
 * <br>使用示例:<br>
 * ```
 * <?php
 * // 左侧菜单说明
 * class Api_Demo extends PhalApi_Api {
 *      /**
 *       * 接口服务名称
 *       * @desc 更多说明
 *       * /
 *      public function index() {
 *      }
 * }
 * ```
 * @license     http://www.phalapi.net/license GPL 协议
 * @link        http://www.phalapi.net/
 * @author      xiaoxunzhao     2015-10-25
 * @modify      Aevit           2014-10-29
 * @modify      shwy            2017-03-02
 * @modify      dogstar         2017-06-17
 */
require_once dirname(__FILE__) . '/../init.php';
$projectName = 'PhalApi开源接口框架';
/**
 * 项目的文件夹名
 * TODO: 请根据需要,修改成你的项目名称
 */
$apiDirName = 'Yfs';
/**
 * 扩展类库
 * TODO: 请根据需要,添加需要显示的扩展路径,即./Api目录的父路径
 */
$libraryPaths = array(
    'Library/User/User',    // User扩展
    'Library/Auth/Auth',    // Auth扩展
    'Library/Qiniu/CDN',    // 七牛扩展
    'Library/WechatMini/WechatMini', // 微信小程序扩展
);
$apiList = new PhalApi_Helper_ApiList($projectName);
$apiList->render($apiDirName, $libraryPaths);
Yfs/Api/Send.php
@@ -5,4 +5,65 @@
class Api_Send extends PhalApi_Api {
    public $alidayu;
    public function __construct(){
        $this->alidayu = Alidayu_Lite::getInstance();
    }
    /**
     * 路由规则
     * @return [type] [description]
     */
    public function getRules(){
        return array(
            'register_sms' => array(
                'phone' => array(
                    'name' => 'phone',
                    'type' => 'string',
                    'require' => true,
                    'desc' => '注册手机号'
                )
            )
        );
    }
    /**
     * 注册短信
     * @desc 发送注册短信
     * @return bool code 操作码,0表示成功, 1表示失败
     * @return string msg 返回提示
     */
    public function register_sms(){
        $rs = array('code' => 0, 'msg' => '');
        $sms_service = new Domain_SmsCode();
        $scene = 'register';
        if($sms_service->check($this->phone, $scene)){
            $code = Common_Util::random(6, 1);
            $send_json_data = json_encode(array('mobile_validate' => $code));
            if($this->alidayu->send($this->phone, $send_json_data, $scene)){
                $data = array();
                $time = time();
                $data['phone'] = $this->phone;
                $data['code'] = $code;
                $data['create_time'] = date('Y-m-d H:i:s', $time);
                $data['expire_time'] = date('Y-m-d H:i:s', $time + 60);
                $data['scene'] = $scene;
                $data['status'] = 0;
                $sms_service->add($data);
                $rs['msg'] = '发送成功';
            }
            else{
                $rs['code'] = 1;
                $rs['msg'] = '发送失败';
            }
        }
        else{
            $rs['code'] = 1;
            $rs['msg'] = '请勿重复发送短信,间隔时间60秒';
        }
        return $rs;
    }
}
Yfs/Api/User.php
@@ -10,38 +10,61 @@
            'register' => array(
                'phone' => array('name' => 'phone', 'type' => 'string', 'require' => true, 'desc' => '用户电话'),
                'password' => array('name' => 'password', 'type' => 'string', 'require' => true, 'desc' => '密码'),
                'code' => array('name' => 'code', 'type' => 'string', 'require' => true, 'desc' => '注册验证码'),
            ),
            'getBaseInfo' => array(
                'userId' => array('name' => 'user_id', 'type' => 'int', 'min' => 1, 'require' => true, 'desc' => '用户ID'),
            'login' => array(
                'phone' => array('name' => 'phone', 'type' => 'string', 'require' => true, 'desc' => '用户电话'),
                'password' => array('name' => 'password', 'type' => 'string', 'require' => true, 'desc' => '密码'),
            ),
            'getMultiBaseInfo' => array(
                'userIds' => array('name' => 'user_ids', 'type' => 'array', 'format' => 'explode', 'require' => true, 'desc' => '用户ID,多个以逗号分割'),
            'getUserInfo' => array(
                'phone' => array('name' => 'phone', 'type' => 'string', 'require' => true, 'desc' => '用户电话'),
            ),
        );
    }
    /**
     * 用户注册
     * @desc 用于用户注册
     * @return bool code 操作码,0表示注册成功, 1表示注册
     * @return string msg 返回提示
     */
    public function register(){
        $rs = array('code' => 0, 'msg' => '', 'info' => array());
        $userService = new Domain_User();
        if($userService->checkPhone($this->phone)){
            $data['phone'] = $this->phone;
            $data['encrypt'] = Common_Util::random(8);
            $data['password'] = md5(md5($this->password).$data['encrypt']);
            $data['nickname'] = $this->phone;
            $data['refresh'] = 5;
            $data['is_open_upload'] = 1;
            $data['video'] = 1;
            $data['create_time'] = date('Y-m-d H:i:s');
            $data['edit_time'] = $data['create_time'];
            $data['is_lock'] = 0;
            $data['role'] = '596f23ab9e74bb85388b4567';
            if($userService->register($data)){
                $rs['msg'] = '用户注册成功';
        $rs = array('code' => 0, 'msg' => '');
        $user_service = new Domain_User();
        if($user_service->checkPhone($this->phone)){
            $sms_service = new Domain_SmsCode();
            $result = $sms_service->checkSmsCode($this->phone, $this->code, 'register');
            if($result == 0){
                $data['phone'] = $this->phone;
                $data['encrypt'] = Common_Util::random(8);
                $data['password'] = md5(md5($this->password).$data['encrypt']);
                $data['nickname'] = $this->phone;
                $data['refresh'] = 5;
                $data['is_open_upload'] = 1;
                $data['video'] = 1;
                $data['create_time'] = date('Y-m-d H:i:s');
                $data['edit_time'] = $data['create_time'];
                $data['is_lock'] = 0;
                $data['role'] = '596f23ab9e74bb85388b4567';
                if($user_service->register($data)){
                    $rs['msg'] = '用户注册成功';
                }
                else{
                    $rs['code'] = 1;
                    $rs['msg'] = '注册失败';
                }
            }
            elseif($result == 1){
                $rs['code'] = 1;
                $rs['msg'] = '手机验证码已失效或已经使用过了,请重新获取验证码';
            }
            elseif($result == 2){
                $rs['code'] = 1;
                $rs['msg'] = '手机验证码错误';
            }
            else{
                $rs['code'] = 1;
                $rs['msg'] = '注册失败';
                $rs['msg'] = '验证码不存在,请重新获取验证码';
            }
        }
        else{
@@ -52,64 +75,62 @@
    }
    /**
     * 用户登录
     * @desc 用于用户登录验证
     * @return bool code 操作码,0表示登录成功, 1表示登录失败
     * @return string msg 返回提示
     */
    public function login(){
        $rs = array('code' => 0, 'msg' => '');
        $user_service = new Domain_User();
        if(!$user_service->checkPhone($this->phone) && $user_service->checkUserStatus($this->phone)){
            if($user_service->login($this->phone, $this->password)){
                $rs['msg'] = '登录验证成功';
            }
            else{
                $rs['code'] = 1;
                $rs['msg'] = '用户手机错误或者密码错误';
            }
        }
        else{
            $rs['code'] = 1;
            $rs['msg'] = '用户手机不存在或已被禁用';
        }
        return $rs;
    }
    /**
     * 获取用户信息
     * @return [type] [description]
     * @desc 获取单个用户记录
     * @return bool code 操作码,0表示成功, 1表示失败
     * @return string msg 返回提示
     * @return object info 用户信息对象
     * @return string info._id 用户id
     * @return string info.phone 手机号码
     * @return string info.encypt 随机码
     * @return string info.password 密码
     * @return string info.nickname 用户昵称
     * @return string info.refresh_frequency 刷新频率
     * @return string info.is_open_upload 是否开启上传
     * @return string info.is_lock 是否被锁定,0表示未锁定,1表示锁定
     */
    public function getUserInfo(){
         $rs = array('code' => 0, 'msg' => '', 'info' => array());
    }
        $user_service = new Domain_User();
        $user = $user_service->getUserInfoByPhone($this->phone);
    /**
     * 获取用户基本信息
     * @desc 用于获取单个用户基本信息
     * @return int code 操作码,0表示成功, 1表示用户不存在
     * @return object info 用户信息对象
     * @return int info.id 用户ID
     * @return string info.name 用户名字
     * @return string info.note 用户来源
     * @return string msg 提示信息
     */
    public function getBaseInfo() {
        $rs = array('code' => 0, 'msg' => '', 'info' => array());
        $domain = new Domain_User();
        $info = $domain->getBaseInfo($this->userId);
        if (empty($info)) {
            DI()->logger->debug('user not found', $this->userId);
        if ($user) {
            $rs['code'] = 0;
            $rs['msg'] = '用户信息获取成功';
            $rs['info'] = $info;
        }
        else{
            $rs['code'] = 1;
            $rs['msg'] = T('user not exists');
            return $rs;
        }
        $rs['info'] = $info;
        return $rs;
    }
    /**
     * 批量获取用户基本信息
     * @desc 用于获取多个用户基本信息
     * @return int code 操作码,0表示成功
     * @return array list 用户列表
     * @return int list[].id 用户ID
     * @return string list[].name 用户名字
     * @return string list[].note 用户来源
     * @return string msg 提示信息
     * @exception 400 参数传递错误
     * @exception 500 服务器内部错误
     */
    public function getMultiBaseInfo() {
        $rs = array('code' => 0, 'msg' => '', 'list' => array());
        $domain = new Domain_User();
        foreach ($this->userIds as $userId) {
            $rs['list'][] = $domain->getBaseInfo($userId);
            DI()->tracer->mark('FINISH_GET_INFO');
            $rs['msg'] = '用户信息不存在';
        }
        return $rs;
    }
}
Yfs/Domain/SmsCode.php
New file
@@ -0,0 +1,65 @@
<?php
class Domain_SmsCode {
    public function __construct(){
        $this->model = new Model_SmsCode();
    }
    public function add($smsInfo) {
        return $this->model->add($smsInfo);
    }
    /**
     * 验证手机短信是否可以发送
     * @param  [type] $phone      [description]
     * @param  [type] $scene [description]
     * @return [type]             [description]
     */
    public function check($phone, $scene = ""){
        if(!empty($scene)){
            $sms = $this->model->getPhoneLastSms(array('phone' => $phone, 'scene' => $scene))[0];
            if($sms){
                return strtotime($sms['create_time']) + 60 < time()?true:false;
            }
            return true;
        }
        else{
            return false;
        }
    }
    /**
     * 验证手机验证码
     * @param  [type] $phone [description]
     * @param  [type] $code  [description]
     * @param  [type] $scene [description]
     * @return [type]        [description]
     */
    public function checkSmsCode($phone, $code, $scene){
        if(!empty($phone) && !empty($code) && !empty($scene)){
            $sms = $this->model->getPhoneLastSms(array('phone' => $phone, 'scene' => $scene))[0];
            if($sms){
                if($sms['status'] == 0 && strtotime($sms['expire_time']) >= time()){
                    if($sms['code'] == $code){
                        $this->model->update(array('status' => 1), array('_id' => $sms['_id']));
                        return 0;
                    }
                    else{
                        return 2;
                    }
                }
                else{
                    return 1;
                }
            }
            else{
                return 3;
            }
        }
        else{
            return 3;
        }
    }
}
Yfs/Domain/User.php
@@ -1,18 +1,73 @@
<?php
/**
 * 用户业务类
 */
class Domain_User {
    public function __construct(){
        $this->model = new Model_User();
    }
    /**
     * 注册
     * @param  [type] $regUserInfo [description]
     * @return [type]              [description]
     */
    public function register($regUserInfo) {
        return $this->model->register($regUserInfo);
    }
    /**
     * 验证手机
     * @param  [type] $phone [description]
     * @return [type]        [description]
     */
    public function checkPhone($phone){
        $user = $this->model->get(array('phone' => $phone));
        $user = $this->getUserInfoByPhone($phone);
        return $user?false:true;
    }
    /**
     * 验证用户是否可用
     * @param  [type] $phone [description]
     * @return [type]        [description]
     */
    public function checkUserStatus($phone){
        $user = $this->getUserInfoByPhone($phone);
        if($user && $user['is_lock'] == 0){
            return true;
        }
        else{
            return false;
        }
    }
    /**
     * 通过手机号查询用户信息
     * @param  [type] $phone [description]
     * @return [type]        [description]
     */
    public function getUserInfoByPhone($phone){
        return $this->model->get(array('phone' => $phone));
    }
    /**
     * 用户登录
     * @return [type] [description]
     */
    public function login($phone, $password){
        $user = $this->getUserInfoByPhone($phone);
        if($user){
            if(md5(md5($password).$user['encrypt']) == $user['password']){
                return true;
            }
            else{
                return false;
            }
        }
        else{
            return false;
        }
    }
}
Yfs/Model/SmsCode.php
New file
@@ -0,0 +1,19 @@
<?php
class Model_SmsCode extends Model_Base{
    public $table = 'sms_code';
    /**
     * 获取某场景下最后一条短信
     * @param  [type] $phone [description]
     * @param  [type] $scene [description]
     * @return [type]        [description]
     */
    public function getPhoneLastSms($query = array()){
        return $this->getList($query, array(), array('_id' => -1), 1);
    }
}