龚哥哥 - 山里男儿 爱生活、做自己!
PHP单例模式 设计模式 面向对象
发表于 2015-8-31 | 浏览(5622) | PHP
<?php

/**
 * 单例模式
 * @author  Devil
 * @version v_0.0.1
 */
class Singleton
{
    private $parem;

    /**
     * [__construct 构造方法]
     * @param [mixed] $param [参数]
     */
    private function __construct($param)
    {
        $this->param = $param;
    }

    /**
     * [Instantiate 静态方法, 用于实例化类]
     * @param  [mixed] $param [参数]
     * @return [object]   [类对象]
     */
    public static function Instantiate($param)
    {
        static $object = null;
        if(!is_object($object)) $object = new self($param);
        return $object;
    }

    /**
     * [Show 测试方法]
     */
    public function Show()
    {
        print_r($this->param);
    }
}

/**
 * 使用列子
 */
$param = array('test', 'demo', 'devil');
$obj = Singleton::Instantiate($param);
$obj->Show();

/**
 * $obj = Singleton::Instantiate($param);
 * 不管在项目中多少次这么对类进行实例化,都不会重复创建类对象。
 * $object 被定义成静态变量,不能被第二次赋值。
 * 只要$object是一个对象就直接返回当前对象,则进行实例化并返回。
 *
 * 单例模式可以防止重复创建对象,减轻内存开销。
 */

?>

阅读全文

PHP支付宝接口类 WEB版 即时到帐接口
发表于 2015-8-31 | 浏览(5760) | PHP
<?php

/**
 * 支付宝支付驱动
 * @author  Devil
 * @version v_1.0.0
 */
class Alipay
{
    private $config;

    /**
     * [__construct 构造方法, 初始化配置信息]
     */
    public function __construct()
    {
        $this->config = array(
            'alipay_key'        =>  '', //key
            'alipay_partner'    =>  '', //partner
            'alipay_account'    =>  '', //支付宝账户名称
            'notify_url'        =>  '', //异步通知地址
            'call_back_url'     =>  '', //同步返回地址
        );
    }

    /**
     * [Payment 生成即时到帐支付信息]
     * @param  [array] $order [订单数据]
     */
    public function Payment($order)
    {
        $param = array(
            'service'           => 'create_direct_pay_by_user',
            'partner'           => $this->config['alipay_partner'],
            '_input_charset'    => 'utf-8',
            'notify_url'        => $this->config['notify_url'],
            'return_url'        => $this->config['call_back_url'],

            /* 业务参数 */
            'subject'           => $order['name'],
            'out_trade_no'      => $order['number_id'],
            'price'             => $order['total_fee'],
            'quantity'          => 1,
            'payment_type'      => 1,

            /* 物流参数 */
            'logistics_type'    => 'EXPRESS',
            'logistics_fee'     => 0,
            'logistics_payment' => 'BUYER_PAY_AFTER_RECEIVE',

            /* 买卖双方信息 */
            'seller_email'      => $this->config['alipay_account']
        );
        ksort($param);
        $string = '';
        $sign  = '';

        foreach($param AS $key=>$val)
        {
            $string .= "$key=" .urlencode($val). "&";
            $sign  .= "$key=$val&";
        }

        $string = substr($string, 0, -1);
        $sign  = md5(substr($sign, 0, -1).$this->config['alipay_key']);
        header('location:https://mapi.alipay.com/gateway.do?'.$string. '&sign='.$sign.'&sign_type=MD5');
    }

    /**
     * [Respond 异步请求处理]
     * @return [string] [成功success, 失败其它]
     */
    public function Respond()
    {
        /* 参数处理 */
        if (!empty($_POST))
        {
            foreach($_POST as $key => $val)
            {
                $_GET[$key] = $val;
            }
        }
        $param = $_GET;
        ksort($param);

        /* 判断是否已经处理过 */
        $this->IsRespond($param);

        /* 签名校验 */
        $sign = '';
        foreach($param AS $key=>$val)
        {
            if($key != 'sign' && $key != 'sign_type' && $key != 'code')
            {
                $sign .= "$key=$val&";
            }
        }
        $sign = md5(substr($sign, 0, -1).$this->config['alipay_key']);
        if($Sign == $param['sign'] && $param['trade_status'] == 'TRADE_SUCCESS')
        {
            //$param['out_trade_no'] 参数是唯一标识符
            exit('success');
        }
    }

    /**
     * [IsRespond 是否处理过操作]
     * @param [array] $param [参数]
     */
    private function IsRespond($param)
    {
        //$param['out_trade_no'] 参数是唯一标识符
        //如果处理过了可以直接exit('success');
    }
}

?>

阅读全文

PHP支付宝支付接口pc+wap MD5加密方式
发表于 2015-8-31 | 浏览(9410) | PHP
<?php

/**
 * 支付宝支付驱动
 * @author  Devil
 * @version V_1.0.0
 */
class AlipayLibrary
{
    /**
     * [__construct 构造方法]
     */
    public function __construct(){}

    /**
     * [SoonPay 立即支付]
     * @param [array] $data [支付信息]
     */
    public function SoonPay($data, $config)
    {
        if(empty($data) || empty($config)) return false;

                //这里判断是否是手机访问,自己写一个方法接口。根据访问终端类型进行区分pc或wap
        if(IsMobile())
        {
            $this->SoonPayMobile($data, $config);
        } else {
            $this->SoonPayWeb($data, $config);
        }
    }

    /**
     * [SoonPayMobile wap支付]
     * @param  [array] $data   [参数列表]
     * @param  [array] $config [配置信息]   
     */
    private function SoonPayMobile($data, $config)
    {
        $request_token = $this->GetRequestToken($data, $config);

        $req_data = '<auth_and_execute_req><request_token>'.$request_token.'</request_token></auth_and_execute_req>';
        $parameter = array(
            'service'               =>   'alipay.wap.auth.authAndExecute',
            'format'                =>   'xml',
            'v'                     =>   '2.0',
            'partner'               =>   $config['id'],
            'sec_id'                =>   'MD5',
            'req_data'              =>   $req_data,
            'request_token'         =>   $request_token
        );

        $param = $this->GetParamSign($parameter, $config);
        header('location:http://wappaygw.alipay.com/service/rest.htm?'.$param['param']. '&sign='.md5($param['sign']));

    }

    /**
     * [GetRequestToken 获取临时token]
     * @param  [array] $data   [参数列表]
     * @param  [array] $config [配置信息]
     * @return [string]        [返回临时token]
     */
    private function GetRequestToken($data, $config)
    {
        $parameter = array(
            'service'               =>   'alipay.wap.trade.create.direct',
            'format'                =>   'xml',
            'v'                     =>   '2.0',
            'partner'               =>   $config['id'],
            'req_id'                =>   $data['order_sn'],
            'sec_id'                =>   'MD5',
            'req_data'              =>   $this->GetReqData($data, $config),
            'subject'               =>   $data['name'],
            'out_trade_no'          =>   $data['order_sn'],
            'total_fee'             =>   $data['total_price'],
            'seller_account_name'   =>   $config['name'],
            'call_back_url'         =>   $data['call_back_url'],
            'notify_url'            =>   $data['notify_url'],
            'out_user'              =>   $data['out_user'],
            'merchant_url'          =>   $data['merchant_url'],
        );

        $param = $this->GetParamSign($parameter, $config);
        $ret = urldecode(file_get_contents('http://wappaygw.alipay.com/service/rest.htm?'.$param['param'].'&sign='.md5($param['sign'])));

        $para_split = explode('&',$ret);
        //把切割后的字符串数组变成变量与数值组合的数组
        foreach ($para_split as $item) {
            //获得第一个=字符的位置
            $nPos = strpos($item,'=');
            //获得字符串长度
            $nLen = strlen($item);
            //获得变量名
            $key = substr($item,0,$nPos);
            //获得数值
            $value = substr($item,$nPos+1,$nLen-$nPos-1);
            //放入数组中
            $para_text[$key] = $value;
        }

        $req = Xml_Array($para_text['res_data']);
        if(empty($req['request_token']))
        {
            exit(header('location:'.__ROOT__.'index.php?g=Info&c=Prompt&f=PromptInfo&state=error&content=支付宝异常错误&url='.__ROOT__));
        }

        return $req['request_token'];
    }

    private function GetReqData($data, $config)
    {
        return '<direct_trade_create_req>
                    <subject>'.$data['name'].'</subject>
                    <out_trade_no>'.$data['order_sn'].'</out_trade_no>
                    <total_fee>'.$data['total_price'].'</total_fee>
                    <seller_account_name>'.$config['name'].'</seller_account_name>
                    <call_back_url>'.$data['call_back_url'].'</call_back_url>
                    <notify_url>'.$data['notify_url'].'</notify_url>
                    <out_user>'.$data['out_user'].'</out_user>
                    <merchant_url>'.$data['merchant_url'].'</merchant_url>
                    <pay_expire>3600</pay_expire>
                    <agent_id>0</agent_id>
                </direct_trade_create_req>';
    }

    /**
     * [SoonPayWeb web支付]
     * @param [array] $data   [订单信息]
     * @param [array] $config [配置信息]
     */
    private function SoonPayWeb($data, $config)
    {
        $parameter = array(
            'service'           => 'create_direct_pay_by_user',
            'partner'           => $config['id'],
            '_input_charset'    => ML_CHARSET,
            'notify_url'        => $data['notify_url'],
            'return_url'        => $data['call_back_url'],

            /* 业务参数 */
            'subject'           => $data['name'],
            'out_trade_no'      => $data['order_sn'],
            'price'             => $data['total_price'],

            'quantity'          => 1,
            'payment_type'      => 1,

            /* 物流参数 */
            'logistics_type'    => 'EXPRESS',
            'logistics_fee'     => 0,
            'logistics_payment' => 'BUYER_PAY_AFTER_RECEIVE',

            /* 买卖双方信息 */
            'seller_email'      => $config['name']
        );

        $param = $this->GetParamSign($parameter, $config);
        header('location:https://mapi.alipay.com/gateway.do?'.$param['param']. '&sign='.md5($param['sign']).'&sign_type=MD5');
    }

    /**
     * [GetParamSign 生成参数和签名]
     * @param  [array] $data   [待生成的参数]
     * @param  [array] $config [配置信息]
     * @return [array]         [生成好的参数和签名]
     */
    private function GetParamSign($data, $config)
    {
        $param = '';
        $sign  = '';
        ksort($data);

        foreach($data AS $key => $val)
        {
            $param .= "$key=" .urlencode($val). "&";
            $sign  .= "$key=$val&";
        }

        return array(
            'param' =>   substr($param, 0, -1),
            'sign'  =>   substr($sign, 0, -1).$config['key']
        );
    }

    /**
     * [Respond 异步处理]
     * @param  [array] $config [配置信息]
     * @return [array|string] [成功返回数据列表,失败返回no]
     */
    public function Respond($config)
    {
        if(empty($config)) return 'no';

        $data = empty($_POST) ? $_GET :  array_merge($_GET, $_POST);
        ksort($data);

        $sign = '';
        $sec = isset($data['sec_id']) ? $data['sec_id'] : '';
        if($sec == 'MD5')
        {
            $data_xml = json_decode(json_encode((array) simplexml_load_string($data['notify_data'])), true);
            $data = array_merge($data, $data_xml);
            $sign = 'service='.$data['service'].'&v='.$data['v'].'&sec_id='.$data['sec_id'].'&notify_data='.$data['notify_data'];
        } else {
            foreach($data AS $key=>$val)
            {
                if ($key != 'sign' && $key != 'sign_type' && $key != 'code')
                {
                    $sign .= "$key=$val&";
                }
            }
            $sign = substr($sign, 0, -1);
        }
        if(!isset($data['sign']) || md5($sign.$config['key']) != $data['sign']) return 'no';

        /* 支付状态 */
        $state = isset($data['trade_status']) ? $data['trade_status'] : $data['result'];
        switch($state)
        {
            case 'TRADE_SUCCESS':
                return $data;
                break;

            case 'TRADE_FINISHED':
                return $data;
                break;

               case 'success':
                return $data;
                break;
        }
        return 'no';
    }

}
?>

阅读全文

PHP图片上传
发表于 2015-8-31 | 浏览(5332) | PHP
<?php

/**
 * 图片上传驱动
 * @author  Devil
 * @version 1.0.0
 */
class ImageLibrary
{
    private $i_path;
    private $i_type;
    private $i_is_new_name;
    private $i_quality;
    private $i_data;

    /**
     * [__construct 构造方法]
     * @param [array] $parameters [参数列表]
     */
    private function __construct($parameters)
    {
        /* 检测是否支持gd */
        $this->IsGD();

        /* 图片类型 */
        $this->i_type = empty($parameters['type']) ? $this->GetImageType() : $parameters['type'];

        /* 图片名称是否使用新名称, 则使用原图片名称 */
        $this->i_is_new_name = (isset($parameters['is_new_name']) && is_bool($parameters['is_new_name'])) ? $parameters['is_new_name'] : true;

        /* jpg图片的质量值, 值越大质量越好 */
        $this->i_quality = max(75, isset($parameters['quality']) ? intval($parameters['quality']) : 75);
    }

    /**
     * [Instance 静态方法实例化本类]
     * @return [object] [实例对象]
     */
    public static function Instance($parameters = array())
    {
        static $object = null;
        if(!is_object($object)) $object = new self($parameters);
        return $object;
    }

    /**
     * [SetParameters 参数设置]
     * @param [array] $parameters [参数列表]
     */
    public function SetParameters($parameters = array())
    {
        if(empty($parameters)) return;
        $this->__construct($parameters);
    }

    /**
     * [Is_GD 检查是否支持gd库]
     */
    private function IsGD()
    {
        if(!isset(gd_info()['GD Version']) || empty(gd_info()['GD Version'])) Api_Return(L('code_412'), 412);
    }

    /**
     * [GetImageType 获取图片后缀类型]
     * @return [array] [图片后缀类型]
     */
    private function GetImageType()
    {
        return array(
            'gif'   => 'image/gif',
            'png'   => 'image/png',
            'jpg'   => 'image/jpeg',
            'bmp'   => 'image/bmp'
        );
    }

    /**
     * [Initialization 基本信息初始化]
     * @param  [array]   $data [临时图片数据]
     * @param  [string]  $path [图片保存路径]
     * @return [boolean]       [true或false]
     */
    private function Initialization($data, $path)
    {
        if(empty($data)) return false;

        /* 图片保存地址 */
        $path .= (substr($path, -1) == '/') ? '' : '/';
        $this->i_path = empty($path) ? '/tmp/image' : $path;

        /* 设置存储路径是否存在 */
        if(!is_dir($this->i_path)) @mkdir($this->i_path, 0777, true);
        if(!@opendir($this->i_path)) exit('dir not access');

        /* 初始化返回数据 */
        $this->i_data = array();

        return true;
    }

    /**
     * [GetNewFileName 获取随机名称]
     * @return [string] [新的名称]
     */
    private function GetNewFileName()
    {
        return date('YmdHis').str_shuffle(rand());
    }

    /**
     * [SaveBaseImages base64图片存储]
     * @param  [array] $data  [需要存储的base数据, 一维数组]
     * @param  [string] $path [存储路径]
     * @return [array]        [返回图片地址, 一维数组]
     */
    public function SaveBaseImages($data, $path)
    {
        if(!$this->Initialization($data, $path)) return null;

        for($i=0; $i<count($data); $i++)
        {
            if(empty($data[$i])) continue;

            $temp_img = str_replace(array("\n", '\n', ' '), '', $data[$i]);
            $img_info = @getimagesize('data://application/octet-stream;base64,'.$temp_img);
            if(empty($img_info['mime'])) continue;

            $type = $this->Is_ImageType($img_info['mime']);
            if($type == 'no') continue;

            $file_name = $this->GetNewFileName().'.'.$type;
            if(file_put_contents($this->i_path.$file_name, base64_decode($temp_img)) !== false) $this->i_data[] = $file_name;
        }
        return $this->i_data;
    }

    /**
     * [SaveBinaryImages 二进制图片保存]
     * @param  [array]  $data [二进制图片数据, 一维数组]
     * @param  [string] $path [存储路径]
     * @return [array]        [返回图片地址, 一维数组]
     */
    public function SaveBinaryImages($data, $path)
    {
        if(!$this->Initialization($data, $path)) return null;

        for($i=0; $i<count($data); $i++)
        {
            if(empty($data[$i])) continue;

            $img_info = getimagesizefromstring($data[$i]);
            if(empty($img_info['mime'])) continue;

            $type = $this->Is_ImageType($img_info['mime']);
            if($type == 'no') continue;

            $file_name = $this->GetNewFileName().'.'.$type;
            if(file_put_contents($this->i_path.$file_name, $data) !== false) $this->i_data[] = $file_name;
        }
        return $this->i_data;
    }

    /**
     * [GetOriginal 获取临时图片文件的原图]
     * @param  [array]  $data [临时图片数据]
     * @param  [string] $path [存储路径]
     * @return [string]       [返回图片地址]
     */
    public function GetOriginal($data, $path)
    {
        if(!$this->Initialization($data, $path)) return '';

        if(empty($data['tmp_name'])) return '';

        $type = $this->Is_ImageType($data['type']);
        if($type == 'no') return '';

        $file_name = $this->GetNewFileName().'.'.$type;

        if(move_uploaded_file($data['tmp_name'], $this->i_path.$file_name)) return $file_name;
        return '';
    }

    /**
     * [GetBinaryCompress 获取指定图片路径的压缩图]
     * @param  [string] $file  [图片地址]
     * @param  [string] $path  [存储路径]
     * @param  [int]    $width [设定图片宽度]
     * @param  [int]    $height[指定图片高度, 不指定则高度按照比例自动计算]
     * @return [string]        [返回图片地址]
     */
    public function GetBinaryCompress($file, $path, $width = 0, $height = 0)
    {
        if(!$this->Initialization($file, $path) || is_array($file) || !file_exists($file)) return '';

        $img_info = pathinfo($file);
        if(empty($img_info['basename'])) return '';

        $type = $this->Is_ImageType($img_info['extension']);
        if($type == 'no') return '';

        $file_name = ($this->i_is_new_name) ? $this->GetNewFileName().'.'.$type : $img_info['basename'];

        if($this->ImageCompress($width, $height, $file, $type, $this->i_path.$file_name)) return $file_name;

        return '';
    }

    /**
     * [GetCompress 获取临时图片文件的压缩图]
     * @param  [array]  $data  [临时图片数据]
     * @param  [string] $path  [存储路径]
     * @param  [int]    $width [设定图片宽度]
     * @param  [int]    $height[指定图片高度, 不指定则高度按照比例自动计算]
     * @return [atring|空字符串] [返回图片存储的名称]
     */
    public function GetCompress($data, $path, $width = 0, $height = 0)
    {
        if(!$this->Initialization($data, $path)) return '';

        if(empty($data['tmp_name'])) return '';

        $type = $this->Is_ImageType($data['type']);
        if($type == 'no') return '';

        $file_name = $this->GetNewFileName().'.'.$type;

        if($this->ImageCompress($width, $height, $data['tmp_name'], $type, $this->i_path.$file_name)) return $file_name;
        return '';
    }

    /**
     * [GetCompressCut 临时图像裁剪]
     * @param [array]   $data       [图像临时数据]
     * @param [string]  $path       [图像存储地址]
     * @param [int]     $width      [指定存储宽度]
     * @param [ing]     $height     [指定存储高度]
     * @param [ing]     $src_x      [裁剪x坐标]
     * @param [ing]     $src_y      [裁剪y坐标]
     * @param [ing]     $src_width  [裁剪区域宽度]
     * @param [ing]     $src_height [裁剪区域高度]
     * @return [atring|空字符串] [返回图片存储的名称]
     */
    function GetCompressCut($data, $path, $width = 0, $height = 0, $src_x = 0, $src_y = 0, $src_width = 0, $src_height = 0)
    {
        if(!$this->Initialization($data, $path)) return '';

        if(empty($data['tmp_name'])) return '';

        $type = $this->Is_ImageType($data['type']);
        if($type == 'no') return '';

        $file_name = $this->GetNewFileName().'.'.$type;

        if($this->ImageCompress($width, $height, $data['tmp_name'], $type, $this->i_path.$file_name, $src_x, $src_y, $src_width, $src_height)) return $file_name;
        return '';
    }

    /**
     * [ImageCompress 图片压缩]
     * @param  [int]    $width [指定图片宽度]
     * @param  [int]    $height[指定图片高度]
     * @param  [string] $file  [原图片地址]
     * @param  [string] $type  [类型]
     * @param  [string] $path  [新图片地址]
     * @return [boolean]       [成功true, 失败false]
     */
    private function ImageCompress($width, $height, $file, $type, $path, $src_x = 0, $src_y = 0, $src_width = 0, $src_height = 0)
    {
        /* 获取图片原本尺寸 */
        list($w, $h) = getimagesize($file);

        /* 尺寸计算 */
        $new_width = ($width > 0 && $w > $width) ? $width : $w;
        $new_height = ($width > 0 && $w > $width) ? (round($h/($w/$width))) : $h;
        if($width > 0 && $height > 0) $new_width = $width;
        if($height > 0) $new_height = $height;

        /* url创建一个新图象 */
        switch($type)
        {
            case 'gif':
                $src_im = @imagecreatefromgif($file);
                break;
            case 'png':
                $src_im = @imagecreatefrompng($file);
                break;
            default:
                $src_im = @imagecreatefromjpeg($file);
        }
        if(!$src_im) return;

        /* 新建一个真彩色图像 */
        $dst_im = imagecreatetruecolor($new_width, $new_height);

        /* 是否裁剪图片 */
        if($src_width > 0 && $src_height > 0)
        {
            /* 新建拷贝大小的真彩图像 */
            $cpd_im = imagecreatetruecolor($src_width, $src_height);

            /* 拷贝图片 */
            imagecopy($cpd_im, $src_im, 0, 0, $src_x, $src_y, $src_width, $src_height);

            /* 图片缩放 */
            $s = imagecopyresampled($dst_im, $cpd_im, 0, 0, 0, 0, $new_width, $new_height, $src_width, $src_height);
        } else {
            /* 图片缩放 */
            $s = imagecopyresampled($dst_im, $src_im, 0, 0, 0, 0, $new_width, $new_height, $w, $h);
        }

        if($s)
        {
            switch($type)
            {
                case 'png':
                    imagepng($dst_im, $path);
                    break;
                case 'gif':
                    imagegif($dst_im, $path);
                    break;
                default:
                    imagejpeg($dst_im, $path, $this->i_quality);
            }
        }
        imagedestroy($dst_im);
        imagedestroy($src_im);

        return $s;
    }

    /**
     * [Is_ImageType 验证后缀名是否合法]
     * @param  [string] $image_type [图片后缀类型]
     * @return [string]             [后缀名或no]
     */
    private function Is_ImageType($image_type)
    {
        if(empty($image_type)) return 'no';
        if(array_key_exists($image_type, $this->i_type)) return $image_type;

        foreach($this->i_type as $key=>$val)
        {
            if($val == $image_type) return $key;
        }
        return 'no';
    }
}
?>

阅读全文

PHP Memcached操作类
发表于 2015-8-31 | 浏览(5564) | PHP
<?php

/**
 * 缓存驱动
 * @author  Devil
 * @version 1.0.0
 */
class CacheLibrary
{
    private $c_obj;
    private $c_time;
    /**
     * [__construct 构造方法]
     */
    public function __construct($host, $port = 11211)
    {
        /* 实例化memcached */
        $this->c_obj = new Memcached();
        if(!$this->c_obj->addServer($host, $port)) Api_Return(L('code_413'), 413);

        /* 基础参数设置 */
        $this->c_time = empty(C('cache')['time']) ? 0 : C('cache')['time'];
    }

    /**
     * [GetTime 获取缓存时间]
     * @return [int] [缓存时间]
     */
    private function GetTime($time = 0)
    {
        return (intval($time) > 0) ? intval($time) : $this->c_time;
    }

    /**
     * [Add 缓存添加]
     * @param  [string]     $key  [索引]
     * @param  [mixed]      $val  [值]
     * @param  [integer]    $time [过期时间(单位秒), 0永久, 或时间戳]
     * @return [boolean]    [成功true, 失败false]
     */
    public function Add($key, $val, $time = 0)
    {
        return $this->c_obj->add($key, $val, $this->GetTime($time));
    }

    /**
     * [Set 缓存替换]
     * @param  [string]     $key  [索引]
     * @param  [mixed]      $val  [值]
     * @param  [integer]    $time [过期时间(单位秒), 0永久, 或时间戳]
     * @return [boolean]    [成功true, 失败false]
     */
    public function Set($key, $val, $time = 0)
    {
        return $this->c_obj->set($key, $val, $this->GetTime($time));
    }

    /**
     * [SetMulti 设置多个索引的缓存数据]
     * @param [type] $key_all [索引数组]
     * @param  [integer]      $time [过期时间(单位秒), 0永久, 或时间戳]
     * @return [boolean]      [成功true, 失败false]
     */
    public function SetMulti($key_all, $time = 0)
    {
        return $this->c_obj->setMulti($key_all, $time);
    }

    /**
     * [Append 向已存在索引后面追加数据]
     * @param [string] $key [索引]
     * @param [string] $val [追加的数据(字符串)]
     */
    public function Append($key, $val)
    {
        $this->setOption();
        return $this->c_obj->append($key, $val);
    }

    /**
     * [Prepend 向已存在索引前面追加数据]
     * @param [string] $key [索引]
     * @param [string] $val [追加的数据(字符串)]
     */
    public function Prepend($key, $val)
    {
        $this->setOption();
        return $this->c_obj->prepend($key, $val);
    }

    /**
     * [Replace 替换已存在索引下的元素]
     * @param  [string]     $key  [索引]
     * @param  [mixed]      $val  [值]
     * @param  [integer]    $time [过期时间(单位秒), 0永久, 或时间戳]
     * @return [boolean]    [成功true, 失败false]
     */
    public function Replace($key, $val, $time = 0)
    {
        $this->c_obj->replace($key, $val, $time);
    }

    /**
     * [setOption 设置选项]
     */
    private function setOption()
    {
        $this->c_obj->setOption(Memcached::OPT_COMPRESSION, false);
    }

    /**
     * [Fetch 抓取下一个结果]
     * @param [string]  $key_all [索引名]
     * @param [boolean] $cas     [是否返回长度, 是true, 否false默认]
     */
    public function Fetch($key_all, $cas = false)
    {
        $this->GetDelayed($key_all, $cas);
        return $this->c_obj->fetch();
    }

    /**
     * [FetchAll 抓取所有剩余的结果]
     * @param [string]  $key_all [索引名]
     * @param [boolean] $cas     [是否返回长度, 是true, 否false默认]
     */
    public function FetchAll($key_all, $cas = false)
    {
        $this->GetDelayed($key_all, $cas);
        return $this->c_obj->fetchAll();
    }

    /**
     * [GetDelayed 请求多个索引]
     * @param [string]  $key_all [索引名]
     * @param [boolean] $cas     [是否返回长度, 是true, 否false默认]
     */
    private function GetDelayed($key_all, $cas)
    {
        $this->c_obj->getDelayed($key_all, $cas);
    }

    /**
     * [Get 缓存获取]
     * @param  [string]  $key  [索引]
     * @return [mixed]   [当前索引对应的数据]
     */
    public function Get($key)
    {
        return $this->c_obj->get($key);
    }

    /**
     * [GetMulti 获取多个索引的缓存数据]
     * @param [type] $key_all [索引数组]
     */
    public function GetMulti($key_all)
    {
        return $this->c_obj->getMulti($key_all);
    }

    /**
     * [Delete 删除一个索引]
     * @param  [string]  $key [索引]
     * @param  [integer] $time [等待时间(单位秒), 0立即, 或时间戳]
     * @return [boolean] [成功true, 失败false]
     */
    public function Delete($key, $time = 0)
    {
        return $this->c_obj->delete($key, $time);
    }

    /**
     * [DeleteMulti 删除多个索引]
     * @param  [array]            $key_all     [索引数组]
     * @param  [integer]          $time [过期时间(单位秒), 0立即, 或时间戳]
     * @return [boolean或array]    [成功true, 失败false]
     */
    public function DeleteMulti($key_all, $time = 0)
    {
        $s = $this->c_obj->deleteMulti($key_all, $time);
        if(empty($s)) return false;
        foreach($s as $key=>$val)
        {
            if($val !== true) if($this->Get($key) == false) $s[$key] = true;
        }
        return $s;
    }

    /**
     * [Flush 作废所有元素]
     * @param  [integer] $time [等待时间(单位秒), 0立即]
     * @return [boolean] [成功true, 失败false]
     */
    public function Flush($time = 0)
    {
        return $this->c_obj->flush($time);
    }
}
?>

阅读全文

PHP生成分页类 前端基于amazeui
发表于 2015-8-31 | 浏览(5862) | PHP
<?php

/**
 * 分页驱动
 * @author  Devil
 * @version v_1.0.0
 */
class PageLibrary
{
    private $page;
    private $total;
    private $number;
    private $bt_number;
    private $where;
    private $page_total;
    private $url;
    private $html;

    /**
     * [__construct description]
     * @param [int]    $param['total']      [数据总数]
     * @param [int]    $param['number']     [每页数据条数]
     * @param [int]    $param['bt_number']  [分页显示按钮个数]
     * @param [array]  $param['where']      [额外条件(键值对)]
     * @param [string] $param['url']        [url地址]
     */
    public function __construct($param = array())
    {
        $this->page = max(1, isset($_REQUEST['page']) ? intval($_REQUEST['page']) : 1);
        $this->total = max(1, isset($param['total']) ? intval($param['total']) : 1);
        $this->number = max(1, isset($param['number']) ? intval($param['number']) : 1);
        $this->bt_number = isset($param['bt_number']) ? intval($param['bt_number']) : 2;
        $this->where = (isset($param['where']) && is_array($param['where'])) ? $param['where'] : '';
        $this->url = isset($param['url']) ? $param['url'] : '';
        $this->page_total = 1;
        $this->html = '';

        /* 参数设置 */
        $this->SetParem();
    }

    /**
     * [SetParem 参数设置]
     */
    private function SetParem()
    {
        /* 防止超出最大页码数 */
        $this->page_total = ceil($this->total/$this->number);
        if($this->page > $this->page_total) $this->page = $this->page_total;

        /* 额外条件url设置 */
        if(!empty($this->where) && is_array($this->where))
        {
            foreach($this->where as $k=>$v) $this->url .= '&'.$k.'='.$v;
        }

    }

    /**
     * [GetPageHtml 获取生成好的分页代码]
     */
    public function GetPageHtml()
    {
        $this->html .= '<ul class="am-pagination am-pagination-centered"><li';
        $this->html .= ($this->page > 1) ? '' : ' class="am-disabled"';
        $this->html .= '><a href="'.$this->url.'&page='.($this->page-1).'" class="meila-radius">&laquo;</a></li>';
        $this->html .= $this->GetButtonNumberHtml();
        $this->html .= '<li';
        $this->html .= ($this->page > 0 && $this->page < $this->page_total) ? '' : ' class="am-disabled"';
        $this->html .= '><a href="'.$this->url.'&page='.($this->page+1).'" class="meila-radius">&raquo;</a></li></ul>';

        return $this->html;
    }

    /**
     * [GetButtonNumberHtml 获取button显示个数的html]
     * @return [string] [按钮个数html代码]
     */
    private function GetButtonNumberHtml()
    {
        $html_before = '';
        $html_after = '';
        $html_page = '<li class="am-active"><a class="meila-radius">'.$this->page.'</a></li>';
        if($this->bt_number > 0)
        {
            /* 前按钮 */
            if($this->page > 1)
            {
                $total = ($this->page-$this->bt_number < 1) ? 1 : $this->page-$this->bt_number;
                for($i=$this->page-1; $i>=$total; $i--)
                {
                    $html_before = '<li><a href="'.$this->url.'&page='.$i.'" class="meila-radius">'.$i.'</a></li>'.$html_before;
                }
            }

            /* 后按钮 */
            if($this->page_total > $this->page)
            {
                $total = ($this->page+$this->bt_number > $this->page_total) ? $this->page_total : $this->page+$this->bt_number;
                for($i=$this->page+1; $i<=$total; $i++)
                {
                    $html_after .= '<li><a href="'.$this->url.'&page='.$i.'" class="meila-radius">'.$i.'</a></li>';
                }
            }
        }
        return $html_before.$html_page.$html_after;
    }

    /**
     * [GetPageStarNumber 获取分页起始值]
     */
    public function GetPageStarNumber()
    {
        return intval(($this->page-1)*$this->number);
    }
}
?>

阅读全文

PHP localhost连接不上MySQL
发表于 2015-8-31 | 浏览(5849) | PHP

连接MySQL数据库有两种方式:TCP/IP(一般理解的端口的那种)和Unix套接字(一般叫socket或者sock)。大部分情况下,可以用localhost代表本机127.0.0.1,但是在MySQL连接时,二者不可混用,而且MySQL中权限设置中localhost与127.0.0.1也是分开设置的。当设置为127.0.0.1时,系统通过TCP/IP方式连接数据库;当设置为localhost时,系统通过socket方式连接数据库。

找到mysql.sock所在位置,常在目录 tmp , var/run/mysqld

修改 php.ini

pdo_mysql.default_socket=/tmp/mysql.sock
mysql.default_socket = /tmp/mysql.sock
mysqli.default_socket = /tmp/mysql.sock

mac重启apache
linux重启php-fpm

阅读全文

PHP PDO操作API
发表于 2015-8-30 | 浏览(5924) | PHP
<?php

/**
 *  DB驱动
 *  @author  Devil
 *  @version v_0.0.1
 */
class DBLibrary
{
    private $obj;

    /**
     * [__construct 构造方法]
     * @param [string]  $host    [连接地址]
     * @param [string]  $name    [数据库名]
     * @param [string]  $user    [用户名]
     * @param [string]  $pwd     [用户密码]
     * @param [boolean] $connect [是否长连接]
     */
    private function __construct($host, $name, $user, $pwd, $connect)
    {
        if(empty($host) || empty($name) || empty($user) || empty($pwd)) exit('Param Error');
        try
        {
            $charset = C('charset');
            $charset = empty($charset) ? 'utf8' : str_replace('-', '', $charset);
            @$this->obj = new PDO("mysql:dbname={$name};host={$host};charset={$charset}", $user, $pwd, array(PDO::ATTR_PERSISTENT=>$connect));

            /* 属性设置 */
            $this->obj->setAttribute(PDO::ATTR_CASE, PDO::CASE_NATURAL);
        }
        catch(PDOException $e)
        {
            exit('DB Connect Fails');
        }
    }

    /**
     * [SetInstance 静态方法]
     * @param string $type [请求类型]
     */
    public static function SetInstance($host, $name, $user, $pwd, $connect = false)
    {
        static $object = null;
        if(!is_object($object)) $object = new self($host, $name, $user, $pwd, $connect);
        return $object;
    }

    /**
     * [Query 查询数据对象]
     * @param  [string] $sql [sql查询语句]
     * @return [obj] [对象]
     */
    private function Query($sql)
    {
        if(empty($sql)) return '';
        try
        {
            $rs = $this->obj->query($sql);
            if(!is_object($rs)) exit('DB Non Object Error');
            $rs->setFetchMode(PDO::FETCH_ASSOC);
            return $rs;
        }
        catch(PDOException $e)
        {
            exit('DB Resources Error');
        }
    }

    /**
     * [GetAll 获取所有数据]
     * @param  [string] $sql [sql查询语句]
     * @return [array|空字符串] [二维数组或空字符串]
     */
    public function GetAll($sql)
    {
        $data = $this->Query($sql)->fetchAll();
        return empty($data) ? '' : $data;
    }

    /**
     * [GetRow 获取一行的数据]
     * @param  [string] $sql [sql查询语句]
     * @return [array|空字符串] [一维数组或空字符串]
     */
    public function GetRow($sql)
    {
        $data = $this->Query($sql)->fetch();
        return empty($data) ? '' : $data;
    }

    /**
     * [GetOne 获取一个字段的数据]
     * @param  [string] $sql [sql查询语句]
     * @return [string|空字符串] [字符串或空字符串]
     */
    public function GetOne($sql)
    {
        $data = $this->Query($sql)->fetchColumn();
        return empty($data) ? '' : $data;
    }

    /**
     * [GetCol 获取所有数据的一列数据]
     * @param  [string] $sql [sql查询语句]
     * @return [array|空字符串] [一维数组或空字符串]
     */
    public function GetCol($sql)
    {
        if(empty($sql)) return '';
        $data = array();
        $rs = $this->obj->query($sql);
        $rs->setFetchMode(PDO::FETCH_NUM);
        while($row = $rs->fetch())
        {
            $data[] = $row[0];
        }
        return empty($data) ? '' : $data;
    }

    /**
     * [Exec 数据更新 删除]
     * @param  [string] $sql [sql操作语句]
     * @return [boolean] [成功true, 失败false]
     */
    public function Exec($sql)
    {
        if($this->obj->exec($sql)) return true;
        return false;
    }

    /**
     * [Insert 数据插入]
     * @param  [string] $sql [sql插入语句]
     * @return [int] [成功返回自增id(表无自增id则0), 失败-1]
     */
    public function Insert($sql)
    {
        if($this->obj->exec($sql)) return $this->obj->lastInsertId();
        return -1;
    }

    /**
     * [StartTrans 开启事物]
     */
    public function StartTrans()
    {
        $this->obj->beginTransaction();
    }

    /**
     * [Commit 提交事物]
     */
    public function Commit()
    {
        $this->obj->commit();
    }

    /**
     * [RollBack 回滚事物]
     */
    public function RollBack()
    {
        $this->obj->rollBack();
    }
}

?>

阅读全文

PHP微信操作API
发表于 2015-8-30 | 浏览(7858) | PHP
<?php

/**
 * 微信消息
 * @author  Devil
 * @version v_0.0.1
 */
class WeiXinIMLibrary
{
    private $appid;
    private $appsecret;
    private $token;
    private $encoding_aes_key;
    private $weixin_name;
    private $file_dir;

    /**
     * [__construct 构造方法]
     * @param [string] $appid            [应用ID]
     * @param [string] $appsecret        [应用密钥]
     * @param [string] $token            [token]
     * @param [string] $encoding_aes_key [加密串]
     * @param [string] $weixin_name      [服务号的微信号]
     */
    private function __construct($appid, $appsecret, $token, $encoding_aes_key, $weixin_name)
    {
        $this->appid = $appid;
        $this->appsecret = $appsecret;
        $this->token = $token;
        $this->encoding_aes_key = $encoding_aes_key;
        $this->weixin_name = $weixin_name;

        $this->file_dir = C('weixin_token_dir');
    }

    /**
     * [Instantiate 静态方法]
     * @param  [string] $appid            [应用ID]
     * @param  [string] $appsecret        [应用密钥]
     * @param  [string] $token            [token]
     * @param  [string] $encoding_aes_key [加密串]
     * @param  [string] $weixin_name      [服务号的微信号]
     * @return [object]                   [实例化对象]
     */
    public static function Instantiate($appid, $appsecret, $token, $encoding_aes_key, $weixin_name)
    {
        $object = null;
        if(!is_object($object)) $object = new self($appid, $appsecret, $token, $encoding_aes_key, $weixin_name);
        return $object;
    }

    /**
     * [Valid 接口配置校验]
     */
    public function Valid()
    {
        $ReturnStr = empty($_GET["echostr"]) ? '' : $_GET["echostr"];
        $SignaTure = empty($_GET["signature"]) ? '' : $_GET["signature"];
        $TimeStamp = empty($_GET["timestamp"]) ? '' : $_GET["timestamp"];
        $Nonce = empty($_GET["nonce"]) ? '' : $_GET["nonce"];

        $TmpArr = array($this->token, $TimeStamp, $Nonce);
        sort($TmpArr);
        $TmpStr = sha1(implode($TmpArr));
        if($TmpStr == $SignaTure) echo $ReturnStr;
    }

    /**
     * [EncryptMsg 将公众平台回复用户的消息加密打包]
     * <ol>
     *    <li>对要发送的消息进行AES-CBC加密</li>
     *    <li>生成安全签名</li>
     *    <li>将消息密文和安全签名打包成xml格式</li>
     * </ol>
     *
     * @param $replyMsg string 公众平台待回复用户的消息,xml格式的字符串
     * @param $timeStamp string 时间戳,可以自己生成,也可以用URL参数的timestamp
     * @param $nonce string 随机串,可以自己生成,也可以用URL参数的nonce
     * @return$encryptMsg string 加密后的可以直接回复用户的密文,包括msg_signature, timestamp, nonce, encrypt的xml格式的字符串,
     *                      当return返回0时有效
     *
     * @return int 成功0,失败返回对应的错误码
     */
    public function EncryptMsg($replyMsg, $timeStamp = '', $nonce = '')
    {
        //加密
        $encrypt = $this->Encrypt($replyMsg);

        if(empty($timeStamp)) $timeStamp = time();
        if(empty($nonce)) $timeStamp = md5(time().rand(0,100));

        //生成安全签名
        $signature = $this->GetSHA1($timeStamp, $nonce, $encrypt);

        //生成发送的xml
        return $this->Generate($encrypt, $signature, $timeStamp, $nonce);
    }

    /**
     * [DecryptMsg 检验消息的真实性,并且获取解密后的明文]
     * <ol>
     *    <li>利用收到的密文生成安全签名,进行签名验证</li>
     *    <li>若验证通过,则提取xml中的加密消息</li>
     *    <li>对消息进行解密</li>
     * </ol>
     *
     * @param $msgSignature string 签名串,对应URL参数的msg_signature
     * @param $timestamp string 时间戳 对应URL参数的timestamp
     * @param $nonce string 随机串,对应URL参数的nonce
     * @param $postData string 密文,对应POST请求的数据
     * @param &$msg string 解密后的原文,当return返回0时有效
     *
     * @return int 成功0,失败返回对应的错误码
     */
    public function DecryptMsg($msgSignature, $timestamp = '', $nonce, $postData)
    {
        if(strlen($this->encoding_aes_key) != 43) exit('encodingAesKey非法');

        //提取密文
        $array = $this->Extract($postData);
        $encrypt = $array[0];
        $touser_name = $array[1];

        if(empty($timestamp)) $timestamp = time();

        //验证安全签名
        $signature = $this->GetSHA1($timestamp, $nonce, $encrypt);
        if($signature != $msgSignature) exit('签名验证错误');

        return $this->Decrypt($encrypt);
    }

    /**
     * [Extract 提取出xml数据包中的加密消息]
     * @param string $xmltext 待提取的xml字符串
     * @return string 提取出的加密消息字符串
     */
    public function Extract($xmltext)
    {
        try {
            $xml = new DOMDocument();
            $xml->loadXML($xmltext);
            $array_e = $xml->getElementsByTagName('Encrypt');
            $array_a = $xml->getElementsByTagName('ToUserName');
            $encrypt = $array_e->item(0)->nodeValue;
            $tousername = $array_a->item(0)->nodeValue;
            return array($encrypt, $tousername);
        } catch (Exception $e) {
            exit('xml解析失败:'.$e->getMessage());
        }
    }

    /**
     * [Generate 生成xml消息]
     * @param string $encrypt 加密后的消息密文
     * @param string $signature 安全签名
     * @param string $timestamp 时间戳
     * @param string $nonce 随机字符串
     */
    public function Generate($encrypt, $signature, $timestamp, $nonce)
    {
        $format = "<xml>
            <Encrypt><![CDATA[%s]]></Encrypt>
            <MsgSignature><![CDATA[%s]]></MsgSignature>
            <TimeStamp>%s</TimeStamp>
            <Nonce><![CDATA[%s]]></Nonce>
            </xml>";
        return sprintf($format, $encrypt, $signature, $timestamp, $nonce);
    }

    /**
     * [GetSHA1 用SHA1算法生成安全签名]
     * @param [string] $timestamp   时间戳
     * @param [string] $nonce       随机字符串
     * @param [string] $encrypt     密文消息
     */
    private function GetSHA1($timestamp, $nonce, $encrypt_msg)
    {
        try {
            $all = array($encrypt_msg, $this->token, $timestamp, $nonce);
            sort($all, SORT_STRING);
            return sha1(implode($all));
        } catch (Exception $e) {
            exit('签名验证错误:'.$e->getMessage());
        }
    }

    /**
     * [Encrypt 对明文进行加密]
     * @param  [string] $text   需要加密的明文
     * @return [string]         加密后的密文
     */
    public function Encrypt($text)
    {
        $encoding_aes_key = base64_decode($this->encoding_aes_key . "=");
        try {
            //获得16位随机字符串,填充到明文之前
            $random = $this->GetRandomStr();
            $text = $random . pack("N", strlen($text)) . $text . $this->appid;

            // 网络字节序
            $size = @mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
            $module = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
            $iv = substr($encoding_aes_key, 0, 16);

            //使用自定义的填充方式对明文进行补位填充
            $text = $this->Encode($text);
            mcrypt_generic_init($module, $encoding_aes_key, $iv);

            //加密
            $encrypted = mcrypt_generic($module, $text);
            mcrypt_generic_deinit($module);
            mcrypt_module_close($module);

            //print(base64_encode($encrypted));
            //使用BASE64对加密后的字符串进行编码
            return base64_encode($encrypted);
        } catch (Exception $e) {
            exit('base64加密失败:'.$e->getMessage());
        }
    }

    /**
     * [Decrypt 对密文进行解密]
     * @param string $encrypted 需要解密的密文
     * @return string 解密得到的明文
     */
    public function Decrypt($encrypted)
    {
        $encoding_aes_key = base64_decode($this->encoding_aes_key . "=");
        try {
            //使用BASE64对需要解密的字符串进行解码
            $ciphertext_dec = base64_decode($encrypted);
            $module = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
            $iv = substr($encoding_aes_key, 0, 16);
            mcrypt_generic_init($module, $encoding_aes_key, $iv);

            //解密
            $decrypted = mdecrypt_generic($module, $ciphertext_dec);
            mcrypt_generic_deinit($module);
            mcrypt_module_close($module);
        } catch (Exception $e) {
            exit('AES解密失败'.$e->getMessage());
        }

        try {
            //去除补位字符
            $result = $this->Decode($decrypted);
            //去除16位随机字符串,网络字节序和AppId
            if (strlen($result) < 16) return "";

            $content = substr($result, 16, strlen($result));
            $len_list = unpack("N", substr($content, 0, 4));
            $xml_len = $len_list[1];
            $xml_content = substr($content, 4, $xml_len);
            $from_appid = substr($content, $xml_len + 4);
        } catch (Exception $e) {
            exit('encodingAesKey非法:'.$e->getMessage());
        }

        if($from_appid != $this->appid) exit('appid校验错误:'.$e->getMessage());

        return $xml_content;
    }

    /**
     * [Encode 对需要加密的明文进行填充补位]
     * @param $text 需要进行填充补位操作的明文
     * @return 补齐明文字符串
     */
    public function Encode($text)
    {
        $block_size = 32;
        $text_length = strlen($text);
        //计算需要填充的位数
        $amount_to_pad = $block_size - ($text_length % $block_size);
        if ($amount_to_pad == 0)
        {
            $amount_to_pad = $block_size;
        }
        //获得补位所用的字符
        $pad_chr = chr($amount_to_pad);
        $tmp = "";
        for ($index = 0; $index < $amount_to_pad; $index++) {
            $tmp .= $pad_chr;
        }
        return $text . $tmp;
    }

    /**
     * [Decode 对解密后的明文进行补位删除]
     * @param decrypted 解密后的明文
     * @return 删除填充补位后的明文
     */
    public function Decode($text)
    {

        $pad = ord(substr($text, -1));
        if ($pad < 1 || $pad > 32) {
            $pad = 0;
        }
        return substr($text, 0, (strlen($text) - $pad));
    }

    /**
     * [GetRandomStr 随机生成16位字符串]
     * @return [string] 生成的字符串
     */
    public function GetRandomStr()
    {
        $str = "";
        $str_pol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
        $max = strlen($str_pol) - 1;
        for ($i = 0; $i < 16; $i++) {
            $str .= $str_pol[mt_rand(0, $max)];
        }
        return $str;
    }

    /**
     * [GetTextXml 文本提示内容]
     * @param  [string] $to_user_name   [接收的用户openid]
     * @param  [string] $this->weixin_name [开发者微信号]
     * @param  [string] $String         [文本内容]
     * @return [string]                 [xml数据]
     */
    public function GetTextXml($to_user_name, $String)
    {
        if(empty($to_user_name) || empty($this->weixin_name) || empty($String)) return '参数有误';
        return '<xml>
                    <ToUserName><![CDATA['.$to_user_name.']]></ToUserName>
                    <FromUserName><![CDATA['.$this->weixin_name.']]></FromUserName>
                    <CreateTime>'.time().'</CreateTime>
                    <MsgType><![CDATA[text]]></MsgType>
                    <Content><![CDATA['.$String.']]></Content>
                 </xml>';
    }

    /**
     * [GetImageXml 图片提示内容]
     * @param  [string] $to_user_name   [接收的用户openid]
     * @param  [string] $ImageId        [图片id]
     * @return [string]                 [xml数据]
     */
    public function GetImageXml($to_user_name, $ImageId)
    {
        if(empty($to_user_name) || empty($this->weixin_name) || empty($ImageId)) return '参数有误';
        return '<xml>
                    <ToUserName><![CDATA['.$to_user_name.']]></ToUserName>
                    <FromUserName><![CDATA['.$this->weixin_name.']]></FromUserName>
                    <CreateTime>'.time().'</CreateTime>
                    <MsgType><![CDATA[image]]></MsgType>
                    <Image>
                        <MediaId><![CDATA['.$ImageId.']]></MediaId>
                    </Image>
                 </xml>';
    }

    /**
     * [GetImageTextXml 图文消息发送]
     * @param  [string] $to_user_name   [接收的用户openid]
     * @param  [array]  $data           [发送的数据]
     *                  array(array('title'=>'标题', 'desc'=>'描述', 'img'=>'图片地址http开头', 'url'=>'指向地址'), ......);
     * @return [string]                 [xml数据]
     */
    public function GetImageTextXml($to_user_name, $data)
    {
        if(empty($to_user_name) || empty($this->weixin_name) || empty($data) || !is_array($data)) return '参数有误';
        $count = count($data);
        if($count > 10) return '不能超过10条数据';

        $xml = '<xml>
                    <ToUserName><![CDATA['.$to_user_name.']]></ToUserName>
                    <FromUserName><![CDATA['.$this->weixin_name.']]></FromUserName>
                    <CreateTime>'.time().'</CreateTime>
                    <MsgType><![CDATA[news]]></MsgType>
                    <ArticleCount>'.$count.'</ArticleCount>
                    <Articles>';

        for($i=0; $i<$count; $i++)
        {
            $title = isset($data[$i]['title']) ? trim($data[$i]['title']) : '';
            $desc = isset($data[$i]['desc']) ? trim($data[$i]['desc']) : '';
            $img = isset($data[$i]['img']) ? trim($data[$i]['img']) : '';
            $url = isset($data[$i]['url']) ? trim($data[$i]['url']) : '';
            $xml .= '<item>
                        <Title><![CDATA['.$title.']]></Title> 
                        <Description><![CDATA['.$desc.']]></Description>
                        <PicUrl><![CDATA['.$img.']]></PicUrl>
                        <Url><![CDATA['.$url.']]></Url>
                    </item>';
        }
        return $xml.'</Articles></xml>';
    }

    /**
     * [GetCustomer 客服回复]
     * @param [type] $to_user_name   [接收的用户openid]
     */
    public function GetCustomer($to_user_name)
    {
        return '<xml>
            <ToUserName><![CDATA['.$to_user_name.']]></ToUserName>
            <FromUserName><![CDATA['.$this->weixin_name.']]></FromUserName>
            <CreateTime>'.time().'</CreateTime>
            <MsgType><![CDATA[transfer_customer_service]]></MsgType>
            </xml>';
    }

    /**
     * [SendTemplates 发送模版消息]
     * @param [type] $touser      [接收者用户openid]
     * @param [type] $template_id [模版id]
     * @param [type] $data        [参数数据]
     * @param [type] $url         [指向url]
     * @param [type] $topcolor    [头顶边线颜色]
     */
    public function SendTemplates($touser, $template_id, $data, $url = '', $topcolor = '')
    {
        if(empty($touser) || empty($template_id) || empty($data) || !is_array($data)) return '参数有误';

        $access_token = $this->getAccessToken();

        $post = array(
                'touser'        =>   $touser,
                'template_id'   =>   $template_id,
                'url'           =>   $url,
                'topcolor'      =>   $topcolor,
                'data'          =>   $data
            );
        $result = json_decode($this->Curl_Post('https://api.weixin.qq.com/cgi-bin/message/template/send?access_token='.$access_token, json_encode($post)), true);

        return (isset($result['errcode']) && $result['errcode'] == 0);
    }

    /**
     * [Curl_Post curl模拟post]
     * @param  [string] $url    [请求地址]
     * @param  [array] $post    [发送的post数据]
     * @return [array]          [返回的数据]
     */
    private function Curl_Post($url, $post = '') {
        $options = array(
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HEADER         => false,
            CURLOPT_POST           => true,
            CURLOPT_POSTFIELDS     => $post,
        );

        $ch = curl_init($url);
        curl_setopt_array($ch, $options);
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }

    public function getSignPackage() {
    $jsapiTicket = $this->getJsApiTicket();

    // 注意 URL 一定要动态获取,不能 hardcode.
    $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
    $url = "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";

    $timestamp = time();
    $nonceStr = $this->createNonceStr();

    // 这里参数的顺序要按照 key 值 ASCII 码升序排序
    $string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";

    $signature = sha1($string);

    $signPackage = array(
      "appId"     => $this->appid,
      "nonceStr"  => $nonceStr,
      "timestamp" => $timestamp,
      "url"       => $url,
      "signature" => $signature,
      "rawString" => $string
    );
    return $signPackage; 
  }

  private function createNonceStr($length = 16) {
    $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    $str = "";
    for ($i = 0; $i < $length; $i++) {
      $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
    }
    return $str;
  }

  private function getJsApiTicket() {
    // jsapi_ticket 应该全局存储与更新,以下代码以写入到文件中做示例
    if(file_exists($this->file_dir."jsapi_ticket.json")) $data = json_decode(file_get_contents($this->file_dir."jsapi_ticket.json"));
    if (empty($data) || $data->expire_time < time()) {
      $accessToken = $this->getAccessToken();
      // 如果是企业号用以下 URL 获取 ticket
      // $url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=$accessToken";
      $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=$accessToken";
      $res = json_decode(file_get_contents($url));
      $ticket = $res->ticket;
      if ($ticket) {
        $data->expire_time = time() + 7000;
        $data->jsapi_ticket = $ticket;
        file_put_contents($this->file_dir."jsapi_ticket.json", json_encode($data));
      }
    } else {
      $ticket = $data->jsapi_ticket;
    }

    return $ticket;
  }

  public function getAccessToken() {
    // access_token 应该全局存储与更新,以下代码以写入到文件中做示例
    if(file_exists($this->file_dir."access_token.json")) $data = json_decode(file_get_contents($this->file_dir."access_token.json"));
    if (empty($data) || $data->expire_time < time()) {
      // 如果是企业号用以下URL获取access_token
      // $url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=$this->appid&corpsecret=$this->appsecret";
      $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$this->appid&secret=$this->appsecret";
      $res = json_decode(file_get_contents($url));
      $access_token = $res->access_token;
      if(!empty($access_token))
      {
        $data->expire_time = time() + 7000;
        $data->access_token = $access_token;
        file_put_contents($this->file_dir."access_token.json", json_encode($data));
      }
    } else {
      $access_token = $data->access_token;
    }
    return $access_token;
  }

}

?>

阅读全文

TOP