Browse Source

增加微信支付

15954078560 2 years ago
parent
commit
8005eca058

+ 58 - 0
application/common.php

@@ -623,4 +623,62 @@ function process_time($time) {
 function getMillisecond() {
     list($t1, $t2) = explode(' ', microtime());
     return (float)sprintf('%.0f', (floatval($t1) + floatval($t2)) * 1000);
+}
+
+/**
+ * CURL请求
+ * @param $url 请求url地址
+ * @param $method 请求方法 get post
+ * @param null $postfields post数据数组
+ * @param array $headers 请求header信息
+ * @param bool|false $debug  调试开启 默认false
+ * @return mixed
+ */
+function httpRequest($url, $method, $postfields = null, $headers = array(), $debug = false) {
+    $method = strtoupper($method);
+    $ci = curl_init();
+    /* Curl settings */
+    curl_setopt($ci, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+    curl_setopt($ci, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0");
+    curl_setopt($ci, CURLOPT_CONNECTTIMEOUT, 60); /* 在发起连接前等待的时间,如果设置为0,则无限等待 */
+    curl_setopt($ci, CURLOPT_TIMEOUT, 7); /* 设置cURL允许执行的最长秒数 */
+    curl_setopt($ci, CURLOPT_RETURNTRANSFER, true);
+    switch ($method) {
+        case "POST":
+            curl_setopt($ci, CURLOPT_POST, true);
+            if (!empty($postfields)) {
+                $tmpdatastr = is_array($postfields) ? http_build_query($postfields) : $postfields;
+                curl_setopt($ci, CURLOPT_POSTFIELDS, $tmpdatastr);
+            }
+            break;
+        default:
+            curl_setopt($ci, CURLOPT_CUSTOMREQUEST, $method); /* //设置请求方式 */
+            break;
+    }
+    $ssl = preg_match('/^https:\/\//i',$url) ? TRUE : FALSE;
+    curl_setopt($ci, CURLOPT_URL, $url);
+    if($ssl){
+        curl_setopt($ci, CURLOPT_SSL_VERIFYPEER, FALSE); // https请求 不验证证书和hosts
+        curl_setopt($ci, CURLOPT_SSL_VERIFYHOST, FALSE); // 不从证书中检查SSL加密算法是否存在
+    }
+    //curl_setopt($ci, CURLOPT_HEADER, true); /*启用时会将头文件的信息作为数据流输出*/
+    //curl_setopt($ci, CURLOPT_FOLLOWLOCATION, 1);
+    curl_setopt($ci, CURLOPT_MAXREDIRS, 2);/*指定最多的HTTP重定向的数量,这个选项是和CURLOPT_FOLLOWLOCATION一起使用的*/
+    curl_setopt($ci, CURLOPT_HTTPHEADER, $headers);
+    curl_setopt($ci, CURLINFO_HEADER_OUT, true);
+    /*curl_setopt($ci, CURLOPT_COOKIE, $Cookiestr); * *COOKIE带过去** */
+    $response = curl_exec($ci);
+    $requestinfo = curl_getinfo($ci);
+    $http_code = curl_getinfo($ci, CURLINFO_HTTP_CODE);
+    if ($debug) {
+        echo "=====post data======\r\n";
+        var_dump($postfields);
+        echo "=====info===== \r\n";
+        print_r($requestinfo);
+        echo "=====response=====\r\n";
+        print_r($response);
+    }
+    curl_close($ci);
+    return $response;
+    //return array($http_code, $response,$requestinfo);
 }

+ 84 - 0
extend/wxpay/Demo.php

@@ -0,0 +1,84 @@
+<?php
+
+/**
+ * 微信插件Demo
+ * @author Jack_YanTC <627495692@qq.com>
+ */
+class Demo {
+
+    //config 示例
+    public $config = array(
+
+        /* 微信支付相关配置 */
+        'WxPay' => array(
+            #微信商户平台应用APPID
+            'app_id' => 'wx278f0cfe8cf5be1c',
+            #商户号
+            'mch_id' => '1482937212',
+            //api密钥
+            'key' => 'yiwenjiaoyuyiwenjiaoyuyiwenjiaoy',
+            #异步回调地址
+            'notify_url' => 'http://yiwen.host3.liuniukeji.com/index.php/Home/Payment/wechatNotify',
+            //公众帐号secert(仅JSAPI支付的时候需要配置)
+            'appsecret' => 'e2970084a53543160d8e93a865d94621',
+        )
+
+    );
+
+
+    //app支付 示例
+    public function appPay() {
+        $data['body'] = '六牛科技';//订单详情
+        $data['out_trade_no'] = '201705201314';//订单号
+        $data['total_fee'] = '0.01';//订单金额元
+        require_once("Plugins/WxPay/WxPay.php");
+        $wxPay = new \WxPay();
+        //返回微信app支付所需字符串
+        $result = $wxPay->WxPayApp($data);
+
+        return $result;
+    }
+
+    //web支付 示例
+    public function webPay() {
+        $data['body'] = '六牛科技';//订单详情
+        $data['out_trade_no'] = '201705201314';//订单号
+        $data['total_fee'] = '0.01';//订单金额元
+        require_once("Plugins/WxPay/WxPay.php");
+        $wxPay = new \WxPay();
+        //返回支付二维码图片的url地址,网页里直接如下调用
+        //<img alt="扫描二扫码支付" src="{$result}"/>;
+        $result = $wxPay->WxPayWeb($data);
+        redirect($result);
+//        $this->result =$result;
+//        $this->display('index');
+    }
+
+    //微信回调地址 示例
+    public function WxNotify() {
+        require_once("Plugins/WxPay/WxPay.php");
+        $wxPay = new \WxPay();
+        //验证是否是微信发送且数据完整
+        $flag = $wxPay->WxPayNotifyCheck();
+        if ($flag['status']) {
+            if ($flag['data']['return_code'] == 'SUCCESS' && $flag['data']['result_code'] == 'SUCCESS') {
+                $out_trade_no = $flag['data']['out_trade_no'];//订单号
+
+                //业务逻辑处理
+                $result = D('Common/Recharge')->notify($out_trade_no);
+
+                if ($result) {
+                    $r_arr['return_code'] = 'SUCCESS';
+                    $r_arr['return_msg'] = '回调成功';
+                    echo $this->arrayToXml($r_arr);
+                    die;
+                }
+            }
+        }
+        $r_arr['return_code'] = 'FAIL';
+        $r_arr['return_msg'] = '回调失败';
+        echo $this->arrayToXml($r_arr);
+        die;
+
+    }
+}

+ 81 - 0
extend/wxpay/OpenSSLAES.php

@@ -0,0 +1,81 @@
+<?php
+/**
+ * Copyright (c) 山东六牛网络科技有限公司 https://liuniukeji.com
+ * @Description    网上开源的OpenSSL加密
+ * @Author         Zhou Zeyang   QQ:751027030
+ * @Copyright      Copyright (c) 山东六牛网络科技有限公司 保留所有版权(https://www.liuniukeji.com)
+ * @Date           2018/6/1
+ * @CreateBy       PHPStorm
+ */
+
+
+
+class OpenSSLAES
+{
+    /**
+     * var string $method 加解密方法,可通过openssl_get_cipher_methods()获得
+     */
+    protected $method;
+
+    /**
+     * var string $secret_key 加解密的密钥
+     */
+    protected $secret_key;
+
+    /**
+     * var string $iv 加解密的向量,有些方法需要设置比如CBC
+     */
+    protected $iv;
+
+    /**
+     * var string $options (不知道怎么解释,目前设置为0没什么问题)
+     */
+    protected $options;
+
+    /**
+     * 构造函数
+     *
+     * @param string $key 密钥
+     * @param string $method 加密方式
+     * @param string $iv iv向量
+     * @param mixed $options 还不是很清楚
+     *
+     */
+    public function __construct($key, $method = 'AES-256-ECB', $iv = '', $options = 0)
+    {
+        // key是必须要设置的
+        $this->secret_key = isset($key) ? $key : exit('key为必须项');
+
+        $this->method = $method;
+
+        $this->iv = $iv;
+
+        $this->options = $options;
+    }
+
+    /**
+     * 加密方法,对数据进行加密,返回加密后的数据
+     *
+     * @param string $data 要加密的数据
+     *
+     * @return string
+     *
+     */
+    public function encrypt($data)
+    {
+        return openssl_encrypt($data, $this->method, $this->secret_key, $this->options, $this->iv);
+    }
+
+    /**
+     * 解密方法,对数据进行解密,返回解密后的数据
+     *
+     * @param string $data 要解密的数据
+     *
+     * @return string
+     *
+     */
+    public function decrypt($data)
+    {
+        return openssl_decrypt($data, $this->method, $this->secret_key, $this->options, $this->iv);
+    }
+}

+ 421 - 0
extend/wxpay/WxPay.php

@@ -0,0 +1,421 @@
+<?php
+
+/**
+ * 微信插件 使用需 require_once("./Plugins/WxPay/WxPay.php");
+ * @author Jack_YanTC <627495692@qq.com>
+ */
+class WxPay {
+
+    /**
+     * 初始化参数
+     *
+     * @param array $options
+     * @param $options ['app_id']  APPID:绑定支付的APPID(必须配置,开户邮件中可查看)
+     * @param $options ['mch_id'] MCHID:商户号(必须配置,开户邮件中可查看)
+     * @param $options ['key'] KEY:商户支付密钥,参考开户邮件设置(必须配置,登录商户平台自行设置)
+     * @param $options ['appsecret'] 公众帐号secert(仅JSAPI支付的时候需要配置),
+     * @param $options ['notify_url'] 支付宝回调地址
+     */
+    public function __construct($options = array()) {
+        $this->config = !empty($options) ? $options : C('WxPay');
+    }
+
+    /**
+     * 微信支付App
+     * @param string $data 业务参数 body out_trade_no total_fee
+     * @param string $data ['out_trade_no'] 订单号  必填
+     * @param string $data ['total_fee'] 订单金额  必填
+     * @param string $data ['body'] 订单详情  必填
+     * @return $response 返回app所需字符串
+     */
+    public function WxPayApp($d) {
+        $wxConfig = $this->config;
+
+        $out_trade_no = $d['out_trade_no'];
+        $total_fee = abs(floatval($d['total_fee'])) * 100;// 微信支付 单位为分
+        $nonce_str = $this->getRandChar(32);
+        $ip = $this->get_client_ip();
+        if ($ip == '::1')
+            $ip = '1.1.1.1';
+        $data ["appid"] = $wxConfig["app_id"];
+        $data ["body"] = $d['body'];
+        $data ["mch_id"] = $wxConfig['mch_id'];
+        $data ["nonce_str"] = $nonce_str;
+        $data ["notify_url"] = $wxConfig["notify_url"];
+        $data ["out_trade_no"] = $out_trade_no;
+        $data ["spbill_create_ip"] = $ip;
+        $data ["total_fee"] = $total_fee;
+        $data ["trade_type"] = "APP";
+        $data['time_expire'] = date('YmdHis', time() + 120);
+        $s = $this->getSign($data);
+        $data ["sign"] = $s;
+        $xml = $this->arrayToXml($data);
+        $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
+        $response = $this->postXmlCurl($xml, $url);
+
+        $re = $this->xmlstr_to_array($response);
+        if ($re ['return_code'] == 'FAIL') {
+            return $re['return_msg'];
+        }
+        // 二次签名
+        $reapp = $this->getOrder($re['prepay_id']);
+        return $reapp;
+    }
+
+    public function WxPayJs($d) {
+        $wxConfig = $this->config;
+
+        $out_trade_no = $d['out_trade_no'];
+        $total_fee = abs(floatval($d['total_fee'])) * 100;// 微信支付 单位为分
+//        $total_fee = 1;// 微信支付 单位为分
+        $nonce_str = $this->getRandChar(32);
+        $ip = $this->get_client_ip();
+        if ($ip == '::1')
+            $ip = '1.1.1.1';
+        $trade_type = 'JSAPI';
+        $post  = [
+            'appid'  =>$wxConfig["app_id"] ,
+            'body'   =>$d['body'],
+            'mch_id' =>$wxConfig['mch_id'],
+            'nonce_str' =>$nonce_str,
+            'notify_url' =>$wxConfig["notify_url"],
+            'openid' =>$d['openid'],
+            'out_trade_no' =>$out_trade_no,
+            'spbill_create_ip' =>$ip,
+            'time_expire' => date('YmdHis', time() + 120),
+            'total_fee' => $total_fee,
+            'trade_type' =>$trade_type,
+        ];
+
+        $sign = $this->sign($post);
+
+        $post_xml = '<xml>
+                        <appid>'.$wxConfig["app_id"].'</appid>
+                        <body>'.$d['body'].'</body>
+                        <mch_id>'.$wxConfig['mch_id'].'</mch_id>
+                        <nonce_str>'.$nonce_str.'</nonce_str>
+                        <notify_url>'.$wxConfig["notify_url"].'</notify_url>
+                        <openid>'.$d['openid'].'</openid>
+                        <out_trade_no>'.$out_trade_no.'</out_trade_no>
+                        <spbill_create_ip>'.$ip.'</spbill_create_ip>
+                        <time_expire>'.$post["time_expire"].'</time_expire>
+                        <total_fee>'.$post["total_fee"].'</total_fee>
+                        <trade_type>'.$trade_type.'</trade_type>
+                        <sign>'.$sign.'</sign>
+                    </xml>';
+
+        $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
+
+        $xml = httpRequest($url,'POST',$post_xml);
+
+        $array = $this->xml($xml);//全要大写1
+
+        if($array['RETURN_CODE'] == 'SUCCESS' && $array['RESULT_CODE'] == 'SUCCESS')
+        {
+
+            $time = (string)time();
+            $tmp = [];
+            $tmp['appId'] = $wxConfig["app_id"];
+            $tmp['nonceStr'] = $nonce_str;
+
+            $tmp['package'] = 'prepay_id='.$array['PREPAY_ID'];
+            $tmp['signType'] = 'MD5';
+            $tmp['timeStamp'] = $time;
+
+            //return ajaxReturn(callback(1,'签名成功',$tmp));
+            $data['state'] = 200;
+            $data['appid'] = $wxConfig["app_id"];
+            $data['timeStamp'] = $time;
+            $data['nonceStr'] = $nonce_str;
+            $data['signType'] = 'MD5';
+            $data['package'] = 'prepay_id='.$array['PREPAY_ID']; //同意下单接口返回的值 prepay_id
+            $data['paySign'] = $this->sign($tmp);
+            $data['out_trade_no']  = $out_trade_no;
+        }
+        else
+        {
+            $data['state'] = 0;
+            $data['text'] = 'error';
+            $data['RETURN_CODE'] = $array['RETURN_CODE'];
+            $data['RESULT_CODE'] = $array['RESULT_CODE'];
+        }
+        return $data;
+    }
+
+    /**
+     * 微信App支付退款申请
+     * @param array $d 业务参数 body out_trade_no total_fee
+     * @param string $data ['out_trade_no'] 订单号  必填
+     * @param string $data ['total_fee'] 订单金额  必填
+     * @return $response 返回app所需字符串
+     */
+    public function WxPayRefund($d) {
+        $wxConfig = $this->config;
+        $out_trade_no = $d['out_trade_no'];
+        $transaction_id = $d['trade_no'];
+        $total_fee = $d['total_amount'];// 微信支付 单位为分
+        $refund_reason = $d['refund_reason'];
+        $nonce_str = $this->getRandChar(32);
+        $data ["appid"] = $wxConfig["app_id"];
+        $data ["mch_id"] = $wxConfig['mch_id'];
+        $data ["nonce_str"] = $nonce_str;
+        if ($wxConfig["refund_notify"]) {
+            $data ["notify_url"] = $wxConfig["refund_notify"];
+        }
+        $data ["out_trade_no"] = $out_trade_no;
+        $data ["transaction_id"] = $transaction_id;
+        $data ["out_refund_no"] = $out_trade_no;
+        $data ["total_fee"] = $total_fee;
+        $data ["refund_fee"] = $total_fee;
+        $data ['refund_desc'] = $refund_reason;
+        $s = $this->getSign($data);
+        $data ["sign"] = $s;
+        $xml = $this->arrayToXml($data);
+        $url = 'https://api.mch.weixin.qq.com/secapi/pay/refund';
+        $response = $this->postXmlCurl($xml, $url);
+        $re = $this->xmlstr_to_array($response);
+        if ($re ['return_code'] == 'FAIL') {
+            return $re['return_msg'];
+        }
+        return $re;
+    }
+
+    /**
+     * 微信退款通知
+     * @return array 验证正确返回状态及订单数据
+     */
+    public function WxPayRefundNotifyCheck() {
+        $postStr = $GLOBALS['HTTP_RAW_POST_DATA'];
+        if (!$postStr) {
+            $postStr = file_get_contents("php://input");
+        }
+        $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
+        if ($postObj === false) {
+            error_log('parse xml error', 3, './wechat_errorlog.txt');
+        }
+        if ($postObj->return_code != 'SUCCESS') {
+            error_log($postObj->return_msg, 3, './wechat_errorlog.txt');
+        }
+        $arr = (array)$postObj;
+        file_put_contents('wx_refund_error_logs.txt', date('Y-m-d H:i:s').'退款数据1!'.json_encode($arr), FILE_APPEND);
+
+        if($arr['return_code'] == 'SUCCESS') {
+            $wxConfig = $this->config;
+            //解密信息
+            require_once("Plugins/WxPay/OpenSSLAES.php");
+            $aes = new \OpenSSLAES(md5($wxConfig['key']));
+            $decrypted = $aes->decrypt($arr['req_info']);
+            $reqObj = simplexml_load_string($decrypted, 'SimpleXMLElement', LIBXML_NOCDATA);
+            $arr['req_info'] = (array)$reqObj;
+            file_put_contents('wx_refund_error_logs.txt', date('Y-m-d H:i:s').'退款数据2!'.json_encode($arr), FILE_APPEND);
+            return array('status' => true, 'data' => $arr);
+        }
+        return array('status' => false);
+    }
+
+    /**
+     * 微信签名验证
+     * @param string $data 业务参数
+     * @return array
+     */
+    public function WxPayNotifyCheck() {
+        $postStr = $GLOBALS['HTTP_RAW_POST_DATA'];
+        if(!$postStr){
+            $postStr = file_get_contents("php://input");
+        }
+
+        $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
+        if ($postObj === false) {
+            error_log('parse xml error', 3, './wechat_errorlog.txt');
+        }
+        if ($postObj->return_code != 'SUCCESS') {
+            error_log($postObj->return_msg, 3, './wechat_errorlog.txt');
+        }
+
+        $arr = (array)$postObj;
+        unset($arr['sign']);
+        if ($this->getSign($arr) == $postObj->sign) {
+            return array('status' => true, 'data' => $arr);
+        } else
+            return array('status' => false);
+    }
+
+    /**
+     * 以下为微信所需相关方法,请勿修改
+     */
+
+
+    // 执行第二次签名,才能返回给客户端使用
+    public function getOrder($prepayId) {
+        $data ["appid"] = $this->config ["app_id"];
+        $data ["noncestr"] = $this->getRandChar(32);;
+        $data ["package"] = "Sign=WXPay";
+        $data ["partnerid"] = $this->config ['mch_id'];
+        $data ["prepayid"] = $prepayId;
+        $data ["timestamp"] = time();
+        $s = $this->getSign($data);
+        $data ["sign"] = $s;
+
+        return $data;
+    }
+
+    //生成签名
+    function getSign($Obj) {
+        foreach ($Obj as $k => $v) {
+            $Parameters [strtolower($k)] = $v;
+        }
+        // 签名步骤一:按字典序排序参数
+        ksort($Parameters);
+        $String = $this->formatBizQueryParaMap($Parameters, false);
+        // echo "【string】 =".$String."</br>";
+        // 签名步骤二:在string后加入KEY
+        $String = $String . "&key=" . $this->config ['key'];
+        // echo "<textarea style='width: 50%; height: 150px;'>$String</textarea> <br />";
+        // 签名步骤三:MD5加密
+        $result_ = strtoupper(md5($String));
+        return $result_;
+    }
+
+    // 获取指定长度的随机字符串
+    function getRandChar($length) {
+        $str = null;
+        $strPol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
+        $max = strlen($strPol) - 1;
+
+        for ($i = 0; $i < $length; $i++) {
+            $str .= $strPol [rand(0, $max)]; // rand($min,$max)生成介于min和max两个数之间的一个随机整数
+        }
+
+        return $str;
+    }
+
+    // 数组转xml
+    function arrayToXml($arr) {
+        $xml = "<xml>";
+        foreach ($arr as $key => $val) {
+            if (is_numeric($val)) {
+                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
+            } else
+                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
+        }
+        $xml .= "</xml>";
+        return $xml;
+    }
+
+    // post https请求,CURLOPT_POSTFIELDS xml格式
+    function postXmlCurl($xml, $url, $second = 30) {
+        // 初始化curl
+        $ch = curl_init();
+        // 超时时间
+        curl_setopt($ch, CURLOPT_TIMEOUT, $second);
+        // 这里设置代理,如果有的话
+        // curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8');
+        // curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
+        curl_setopt($ch, CURLOPT_URL, $url);
+        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
+        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
+        // 设置header
+        curl_setopt($ch, CURLOPT_HEADER, FALSE);
+        // 要求结果为字符串且输出到屏幕上
+        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
+        // post提交方式
+        curl_setopt($ch, CURLOPT_POST, TRUE);
+        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
+        // 证书
+        curl_setopt($ch, CURLOPT_SSLKEY, dirname(__FILE__) . '/cert/apiclient_key.pem');
+        curl_setopt($ch, CURLOPT_SSLCERT, dirname(__FILE__) . '/cert/apiclient_cert.pem');
+        // 运行curl
+        $data = curl_exec($ch);
+        // 返回结果
+        if ($data) {
+            curl_close($ch);
+            return $data;
+        } else {
+            $error = curl_errno($ch);
+            echo "curl出错,错误码:$error" . "<br>";
+            echo "<a href='http://curl.haxx.se/libcurl/c/libcurl-errors.html'>错误原因查询</a></br>";
+            curl_close($ch);
+            return false;
+        }
+    }
+
+    //获取当前服务器的IP
+    function get_client_ip() {
+        if ($_SERVER ['REMOTE_ADDR']) {
+            $cip = $_SERVER ['REMOTE_ADDR'];
+        } elseif (getenv("REMOTE_ADDR")) {
+            $cip = getenv("REMOTE_ADDR");
+        } elseif (getenv("HTTP_CLIENT_IP")) {
+            $cip = getenv("HTTP_CLIENT_IP");
+        } else {
+            $cip = "unknown";
+        }
+        return $cip;
+    }
+
+    // 将数组转成uri字符串
+    function formatBizQueryParaMap($paraMap, $urlencode) {
+        $buff = "";
+        ksort($paraMap);
+        foreach ($paraMap as $k => $v) {
+            if ($urlencode) {
+                $v = urlencode($v);
+            }
+            $buff .= strtolower($k) . "=" . $v . "&";
+        }
+
+        if (strlen($buff) > 0) {
+            $reqPar = substr($buff, 0, strlen($buff) - 1);
+        }
+        return $reqPar;
+    }
+
+    //xml转成数组
+    function xmlstr_to_array($xmlstr) {
+        $doc = new \DOMDocument ();
+        $doc->loadXML($xmlstr);
+        return $this->domnode_to_array($doc->documentElement);
+    }
+
+    //dom转成数组
+    function domnode_to_array($node) {
+        $output = array();
+        switch ($node->nodeType) {
+            case XML_CDATA_SECTION_NODE :
+            case XML_TEXT_NODE :
+                $output = trim($node->textContent);
+                break;
+            case XML_ELEMENT_NODE :
+                for ($i = 0, $m = $node->childNodes->length; $i < $m; $i++) {
+                    $child = $node->childNodes->item($i);
+                    $v = $this->domnode_to_array($child);
+                    if (isset ($child->tagName)) {
+                        $t = $child->tagName;
+                        if (!isset ($output [$t])) {
+                            $output [$t] = array();
+                        }
+                        $output [$t] [] = $v;
+                    } elseif ($v) {
+                        $output = ( string )$v;
+                    }
+                }
+                if (is_array($output)) {
+                    if ($node->attributes->length) {
+                        $a = array();
+                        foreach ($node->attributes as $attrName => $attrNode) {
+                            $a [$attrName] = ( string )$attrNode->value;
+                        }
+                        $output ['@attributes'] = $a;
+                    }
+                    foreach ($output as $t => $v) {
+                        if (is_array($v) && count($v) == 1 && $t != '@attributes') {
+                            $output [$t] = $v [0];
+                        }
+                    }
+                }
+                break;
+        }
+        return $output;
+    }
+
+}

BIN
extend/wxpay/cert/apiclient_cert.p12


+ 24 - 0
extend/wxpay/cert/apiclient_cert.pem

@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIID9jCCAt6gAwIBAgIUTxoos4GyDI2SZ7iQjk9JLtgl1AcwDQYJKoZIhvcNAQEL
+BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT
+FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg
+Q0EwHhcNMjAxMjMxMDIyMTM5WhcNMjUxMjMwMDIyMTM5WjCBhzETMBEGA1UEAwwK
+MTYwNTI5MDM2NjEbMBkGA1UECgwS5b6u5L+h5ZWG5oi357O757ufMTMwMQYDVQQL
+DCrlub/opb/ot5HpgJ/ppJDppa7phY3pgIHmnI3liqHmnInpmZDlhazlj7gxCzAJ
+BgNVBAYMAkNOMREwDwYDVQQHDAhTaGVuWmhlbjCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAL8NYSLOjjwtmr5q+U5qafLvihwOLFoHgUi4DF8Md+l+dOJB
+7+jstazIHN96eX8Obr/r1gVaZN70mAt9chJenE/rBRNJPO5FN8EgJCptLvWC16W0
+EoxRBdghzWWSTeRIk6ILqvg6P7rANc4foLc0cAH/aYKdyg2I4iomMZMGnDmDQS/I
+Ed5y4cQoYHiLLtAelgJ8jElUDhVTW9kmrgg15igeTZhcAfu/oq1CE7mKIQJnclkE
+kPTsaKR2VjM5NNTqbKAeqZ8CjSNagRDAYuEKEs2DIs9GXXzKF5RTg4zJOY+rY+BK
+Sjj/uHvU+lbHahilOQTG1JnamHEcrCRkOiJIkRMCAwEAAaOBgTB/MAkGA1UdEwQC
+MAAwCwYDVR0PBAQDAgTwMGUGA1UdHwReMFwwWqBYoFaGVGh0dHA6Ly9ldmNhLml0
+cnVzLmNvbS5jbi9wdWJsaWMvaXRydXNjcmw/Q0E9MUJENDIyMEU1MERCQzA0QjA2
+QUQzOTc1NDk4NDZDMDFDM0U4RUJEMjANBgkqhkiG9w0BAQsFAAOCAQEAnClHBFkW
+0qkMhuGcWRkvAV3jPIkmjrv68HgiVTt/kLA9JBNw2pc+9jcHbKuZU/n8P4sxjQQq
+WYV64ykWvf2vplqRxDu0XKH7AAdNRJt8xWC3PPJlzjQtqwgQCjhUD4bqd/gXWDJ8
+BIA7YUlzswy78+WMmVBYoy2AGZ5VslLVUjAuRnyuKrgjtVYqOsQM0s6IPI+HulW/
+WobDYzN32z5pCRI6rTCu1tDcsTJKgzKXIftqZ8NNEHkbDea1APq7FVt2D6e9sWR7
+vph4mK5SLLkBLR0XoUk2euNQd5wYABuHQcJGPBRfGWkgGasDf1TOnOoIYPdq7ocu
+clkKyBAsarj9xQ==
+-----END CERTIFICATE-----

+ 28 - 0
extend/wxpay/cert/apiclient_key.pem

@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC/DWEizo48LZq+
+avlOamny74ocDixaB4FIuAxfDHfpfnTiQe/o7LWsyBzfenl/Dm6/69YFWmTe9JgL
+fXISXpxP6wUTSTzuRTfBICQqbS71gteltBKMUQXYIc1lkk3kSJOiC6r4Oj+6wDXO
+H6C3NHAB/2mCncoNiOIqJjGTBpw5g0EvyBHecuHEKGB4iy7QHpYCfIxJVA4VU1vZ
+Jq4INeYoHk2YXAH7v6KtQhO5iiECZ3JZBJD07GikdlYzOTTU6mygHqmfAo0jWoEQ
+wGLhChLNgyLPRl18yheUU4OMyTmPq2PgSko4/7h71PpWx2oYpTkExtSZ2phxHKwk
+ZDoiSJETAgMBAAECggEBALmB8UaNz9go4+9vCYIVm6iS5MSXEoOcc/E7HHASOEDV
+VAL5yUyew0zwxfBNCLnRNsJN6XMrMXS3hQbrGJ8zlI2ZA0WVwH8PYLK6VcOIXqdv
+E5tG/ReX+JfDQqAUbmNyAT/AGpOKY6Uey1/IoBIj7XpTGY0FT1LTDd+lVE+RhJHl
+63lzGYtu2nt0sa7Sy9e0O4emPFDHux8T0PHyMa0SizxppMFc37MGMHg2Xt2A9cnO
+t4yNmCv+UlKaY06gu2saklUPAE4LDO0wpPiEu189iJv89uIedNLBpqzYx32VcvAC
+lr3hObdNu+MHV15MTMBAGn05uhslg8nnkznEja8K8SECgYEA9zXvIJRBMVO5TtyO
+s9f1lq5kHLc83RYZxiXCjG5FborsNUH/MMRWMZ/qJV68fnjyBcKZiTB61BEmL5nT
+SwMxkTYr6WHe3kyzx+254wuX7yWvyA/URZ09n6ETK61ArIafS9D0OItEyldqt/I5
+TfTsSVtQSm2onQkYOkCyeGY9F4MCgYEAxdhNRBaAb0Uxzo2Fl3Y9J8if/jljdnhO
+yBS95Y7NjQY6KAfkfJs3sBkbciBwaPpEncuNc6X0sNtmwIVfKaTVifZ6+niDOE41
++byQ9RpJboU76UreEbzFwOd+lbp+kWHeIPsc7cWQd6Gdv1W1MEe7e9cQ9o4lu4Ia
+zMMnVml+2zECgYEAgLIdSTKlNc7GW93KlKnK+qTTDXf/QYGt7U/fFkiZ8NB148v1
+1CeCT9dWiBnnu1evd3w1fgw1BY3f+Uv1icmh1l0DQz5mTghUV7LU4PQ6Jo/SES7c
+bVlMqXurhUNuteJnr4qaeY1XRJd5wUViu8jT8eSNyhGIhCgl6r2fq7pd940CgYAT
+IufeVRrZKGU36GJqkwo5ReOL0Hs5Y0ujeLYhdR2WrWqEorbMAqtxQgxwjoiw7rwi
+UyT8canoTWBz8LKSsZnh/VBJ18xBbvczj7SpsIA3y3VPDGnMZ2jtTrbkvqQtZbz5
+jbBvozNlDuHWNvEOmXGd+eBvKLKnn17+PUYZypx1kQKBgBH8zzW+sZ/BrmfSNOau
+seJPTt3KTy7bHxXf2TOfWcbqPGh6hoQTwAxRyqttkGIT/6xG9PPNtPq4ptvpFiGL
+qVYXC35lvN8r5E+8BVch6VPJ+Ewdz83UlpCwYrpf4HLBaWd9xQnxppbw+8gHM+PK
+fNQe3QlhThZGdcAUfEPuQMsY
+-----END PRIVATE KEY-----

+ 18 - 0
extend/wxpay/cert/证书使用说明.txt

@@ -0,0 +1,18 @@
+欢迎使用微信支付!
+附件中的三份文件(证书pkcs12格式、证书pem格式、证书密钥pem格式),为接口中强制要求时需携带的证书文件。
+证书属于敏感信息,请妥善保管不要泄露和被他人复制。
+不同开发语言下的证书格式不同,以下为说明指引:
+    证书pkcs12格式(apiclient_cert.p12)
+        包含了私钥信息的证书文件,为p12(pfx)格式,由微信支付签发给您用来标识和界定您的身份
+        部分安全性要求较高的API需要使用该证书来确认您的调用身份
+        windows上可以直接双击导入系统,导入过程中会提示输入证书密码,证书密码默认为您的商户号(如:1900006031)
+    证书pem格式(apiclient_cert.pem)
+        从apiclient_cert.p12中导出证书部分的文件,为pem格式,请妥善保管不要泄漏和被他人复制
+        部分开发语言和环境,不能直接使用p12文件,而需要使用pem,所以为了方便您使用,已为您直接提供
+        您也可以使用openssl命令来自己导出:openssl pkcs12 -clcerts -nokeys -in apiclient_cert.p12 -out apiclient_cert.pem
+    证书密钥pem格式(apiclient_key.pem)
+        从apiclient_cert.p12中导出密钥部分的文件,为pem格式
+        部分开发语言和环境,不能直接使用p12文件,而需要使用pem,所以为了方便您使用,已为您直接提供
+        您也可以使用openssl命令来自己导出:openssl pkcs12 -nocerts -in apiclient_cert.p12 -out apiclient_key.pem
+备注说明:  
+        由于绝大部分操作系统已内置了微信支付服务器证书的根CA证书,  2018年3月6日后, 不再提供CA证书文件(rootca.pem)下载 

+ 207 - 0
extend/wxpay/example/WxPay.JsApiPay.php

@@ -0,0 +1,207 @@
+<?php
+require_once "../lib/WxPay.Api.php";
+/**
+ * 
+ * JSAPI支付实现类
+ * 该类实现了从微信公众平台获取code、通过code获取openid和access_token、
+ * 生成jsapi支付js接口所需的参数、生成获取共享收货地址所需的参数
+ * 
+ * 该类是微信支付提供的样例程序,商户可根据自己的需求修改,或者使用lib中的api自行开发
+ * 
+ * @author widy
+ *
+ */
+class JsApiPay
+{
+	/**
+	 * 
+	 * 网页授权接口微信服务器返回的数据,返回样例如下
+	 * {
+	 *  "access_token":"ACCESS_TOKEN",
+	 *  "expires_in":7200,
+	 *  "refresh_token":"REFRESH_TOKEN",
+	 *  "openid":"OPENID",
+	 *  "scope":"SCOPE",
+	 *  "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
+	 * }
+	 * 其中access_token可用于获取共享收货地址
+	 * openid是微信支付jsapi支付接口必须的参数
+	 * @var array
+	 */
+	public $data = null;
+	
+	/**
+	 * 
+	 * 通过跳转获取用户的openid,跳转流程如下:
+	 * 1、设置自己需要调回的url及其其他参数,跳转到微信服务器https://open.weixin.qq.com/connect/oauth2/authorize
+	 * 2、微信服务处理完成之后会跳转回用户redirect_uri地址,此时会带上一些参数,如:code
+	 * 
+	 * @return 用户的openid
+	 */
+	public function GetOpenid()
+	{
+		//通过code获得openid
+		if (!isset($_GET['code'])){
+			//触发微信返回code码
+			$baseUrl = urlencode('http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'].$_SERVER['QUERY_STRING']);
+			$url = $this->__CreateOauthUrlForCode($baseUrl);
+			Header("Location: $url");
+			exit();
+		} else {
+			//获取code码,以获取openid
+		    $code = $_GET['code'];
+			$openid = $this->getOpenidFromMp($code);
+			return $openid;
+		}
+	}
+	
+	/**
+	 * 
+	 * 获取jsapi支付的参数
+	 * @param array $UnifiedOrderResult 统一支付接口返回的数据
+	 * @throws WxPayException
+	 * 
+	 * @return json数据,可直接填入js函数作为参数
+	 */
+	public function GetJsApiParameters($UnifiedOrderResult)
+	{
+		if(!array_key_exists("appid", $UnifiedOrderResult)
+		|| !array_key_exists("prepay_id", $UnifiedOrderResult)
+		|| $UnifiedOrderResult['prepay_id'] == "")
+		{
+			throw new WxPayException("参数错误");
+		}
+		$jsapi = new WxPayJsApiPay();
+		$jsapi->SetAppid($UnifiedOrderResult["appid"]);
+		$timeStamp = time();
+		$jsapi->SetTimeStamp("$timeStamp");
+		$jsapi->SetNonceStr(WxPayApi::getNonceStr());
+		$jsapi->SetPackage("prepay_id=" . $UnifiedOrderResult['prepay_id']);
+		$jsapi->SetSignType("MD5");
+		$jsapi->SetPaySign($jsapi->MakeSign());
+		$parameters = json_encode($jsapi->GetValues());
+		return $parameters;
+	}
+	
+	/**
+	 * 
+	 * 通过code从工作平台获取openid机器access_token
+	 * @param string $code 微信跳转回来带上的code
+	 * 
+	 * @return openid
+	 */
+	public function GetOpenidFromMp($code)
+	{
+		$url = $this->__CreateOauthUrlForOpenid($code);
+		//初始化curl
+		$ch = curl_init();
+		//设置超时
+		curl_setopt($ch, CURLOPT_TIMEOUT, $this->curl_timeout);
+		curl_setopt($ch, CURLOPT_URL, $url);
+		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,FALSE);
+		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,FALSE);
+		curl_setopt($ch, CURLOPT_HEADER, FALSE);
+		curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
+		if(WxPayConfig::CURL_PROXY_HOST != "0.0.0.0" 
+			&& WxPayConfig::CURL_PROXY_PORT != 0){
+			curl_setopt($ch,CURLOPT_PROXY, WxPayConfig::CURL_PROXY_HOST);
+			curl_setopt($ch,CURLOPT_PROXYPORT, WxPayConfig::CURL_PROXY_PORT);
+		}
+		//运行curl,结果以jason形式返回
+		$res = curl_exec($ch);
+		curl_close($ch);
+		//取出openid
+		$data = json_decode($res,true);
+		$this->data = $data;
+		$openid = $data['openid'];
+		return $openid;
+	}
+	
+	/**
+	 * 
+	 * 拼接签名字符串
+	 * @param array $urlObj
+	 * 
+	 * @return 返回已经拼接好的字符串
+	 */
+	private function ToUrlParams($urlObj)
+	{
+		$buff = "";
+		foreach ($urlObj as $k => $v)
+		{
+			if($k != "sign"){
+				$buff .= $k . "=" . $v . "&";
+			}
+		}
+		
+		$buff = trim($buff, "&");
+		return $buff;
+	}
+	
+	/**
+	 * 
+	 * 获取地址js参数
+	 * 
+	 * @return 获取共享收货地址js函数需要的参数,json格式可以直接做参数使用
+	 */
+	public function GetEditAddressParameters()
+	{	
+		$getData = $this->data;
+		$data = array();
+		$data["appid"] = WxPayConfig::APPID;
+		$data["url"] = "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
+		$time = time();
+		$data["timestamp"] = "$time";
+		$data["noncestr"] = "1234568";
+		$data["accesstoken"] = $getData["access_token"];
+		ksort($data);
+		$params = $this->ToUrlParams($data);
+		$addrSign = sha1($params);
+		
+		$afterData = array(
+			"addrSign" => $addrSign,
+			"signType" => "sha1",
+			"scope" => "jsapi_address",
+			"appId" => WxPayConfig::APPID,
+			"timeStamp" => $data["timestamp"],
+			"nonceStr" => $data["noncestr"]
+		);
+		$parameters = json_encode($afterData);
+		return $parameters;
+	}
+	
+	/**
+	 * 
+	 * 构造获取code的url连接
+	 * @param string $redirectUrl 微信服务器回跳的url,需要url编码
+	 * 
+	 * @return 返回构造好的url
+	 */
+	private function __CreateOauthUrlForCode($redirectUrl)
+	{
+		$urlObj["appid"] = WxPayConfig::APPID;
+		$urlObj["redirect_uri"] = "$redirectUrl";
+		$urlObj["response_type"] = "code";
+		$urlObj["scope"] = "snsapi_base";
+		$urlObj["state"] = "STATE"."#wechat_redirect";
+		$bizString = $this->ToUrlParams($urlObj);
+		return "https://open.weixin.qq.com/connect/oauth2/authorize?".$bizString;
+	}
+	
+	/**
+	 * 
+	 * 构造获取open和access_toke的url地址
+	 * @param string $code,微信跳转带回的code
+	 * 
+	 * @return 请求的url
+	 */
+	private function __CreateOauthUrlForOpenid($code)
+	{
+		$urlObj["appid"] = WxPayConfig::APPID;
+		$urlObj["secret"] = WxPayConfig::APPSECRET;
+		$urlObj["code"] = $code;
+		$urlObj["grant_type"] = "authorization_code";
+		$bizString = $this->ToUrlParams($urlObj);
+		return "https://api.weixin.qq.com/sns/oauth2/access_token?".$bizString;
+	}
+}

+ 147 - 0
extend/wxpay/example/WxPay.MicroPay.php

@@ -0,0 +1,147 @@
+<?php
+require_once "../lib/WxPay.Api.php";
+/**
+ * 
+ * 刷卡支付实现类
+ * 该类实现了一个刷卡支付的流程,流程如下:
+ * 1、提交刷卡支付
+ * 2、根据返回结果决定是否需要查询订单,如果查询之后订单还未变则需要返回查询(一般反复查10次)
+ * 3、如果反复查询10订单依然不变,则发起撤销订单
+ * 4、撤销订单需要循环撤销,一直撤销成功为止(注意循环次数,建议10次)
+ * 
+ * 该类是微信支付提供的样例程序,商户可根据自己的需求修改,或者使用lib中的api自行开发,为了防止
+ * 查询时hold住后台php进程,商户查询和撤销逻辑可在前端调用
+ * 
+ * @author widy
+ *
+ */
+class MicroPay
+{
+	/**
+	 * 
+	 * 提交刷卡支付,并且确认结果,接口比较慢
+	 * @param WxPayMicroPay $microPayInput
+	 * @throws WxpayException
+	 * @return 返回查询接口的结果
+	 */
+	public function pay($microPayInput)
+	{
+		//①、提交被扫支付
+		$result = WxPayApi::micropay($microPayInput, 5);
+		//如果返回成功
+		if(!array_key_exists("return_code", $result)
+			|| !array_key_exists("out_trade_no", $result)
+			|| !array_key_exists("result_code", $result))
+		{
+			echo "接口调用失败,请确认是否输入是否有误!";
+			throw new WxPayException("接口调用失败!");
+		}
+		
+		//签名验证
+		$out_trade_no = $microPayInput->GetOut_trade_no();
+		
+		//②、接口调用成功,明确返回调用失败
+		if($result["return_code"] == "SUCCESS" &&
+		   $result["result_code"] == "FAIL" && 
+		   $result["err_code"] != "USERPAYING" && 
+		   $result["err_code"] != "SYSTEMERROR")
+		{
+			return false;
+		}
+
+		//③、确认支付是否成功
+		$queryTimes = 10;
+		while($queryTimes > 0)
+		{
+			$succResult = 0;
+			$queryResult = $this->query($out_trade_no, $succResult);
+			//如果需要等待1s后继续
+			if($succResult == 2){
+				sleep(2);
+				continue;
+			} else if($succResult == 1){//查询成功
+				return $queryResult;
+			} else {//订单交易失败
+				return false;
+			}
+		}
+		
+		//④、次确认失败,则撤销订单
+		if(!$this->cancel($out_trade_no))
+		{
+			throw new WxpayException("撤销单失败!");
+		}
+
+		return false;
+	}
+	
+	/**
+	 * 
+	 * 查询订单情况
+	 * @param string $out_trade_no  商户订单号
+	 * @param int $succCode         查询订单结果
+	 * @return 0 订单不成功,1表示订单成功,2表示继续等待
+	 */
+	public function query($out_trade_no, &$succCode)
+	{
+		$queryOrderInput = new WxPayOrderQuery();
+		$queryOrderInput->SetOut_trade_no($out_trade_no);
+		$result = WxPayApi::orderQuery($queryOrderInput);
+		
+		if($result["return_code"] == "SUCCESS" 
+			&& $result["result_code"] == "SUCCESS")
+		{
+			//支付成功
+			if($result["trade_state"] == "SUCCESS"){
+				$succCode = 1;
+			   	return $result;
+			}
+			//用户支付中
+			else if($result["trade_state"] == "USERPAYING"){
+				$succCode = 2;
+				return false;
+			}
+		}
+		
+		//如果返回错误码为“此交易订单号不存在”则直接认定失败
+		if($result["err_code"] == "ORDERNOTEXIST")
+		{
+			$succCode = 0;
+		} else{
+			//如果是系统错误,则后续继续
+			$succCode = 2;
+		}
+		return false;
+	}
+	
+	/**
+	 * 
+	 * 撤销订单,如果失败会重复调用10次
+	 * @param string $out_trade_no
+	 * @param 调用深度 $depth
+	 */
+	public function cancel($out_trade_no, $depth = 0)
+	{
+		if($depth > 10){
+			return false;
+		}
+		
+		$clostOrder = new WxPayReverse();
+		$clostOrder->SetOut_trade_no($out_trade_no);
+		$result = WxPayApi::reverse($clostOrder);
+		
+		//接口调用失败
+		if($result["return_code"] != "SUCCESS"){
+			return false;
+		}
+		
+		//如果结果为success且不需要重新调用撤销,则表示撤销成功
+		if($result["result_code"] != "SUCCESS" 
+			&& $result["recall"] == "N"){
+			return true;
+		} else if($result["recall"] == "Y") {
+			return $this->cancel($out_trade_no, ++$depth);
+		}
+		return false;
+	}
+}

+ 56 - 0
extend/wxpay/example/WxPay.NativePay.php

@@ -0,0 +1,56 @@
+<?php
+require_once "../lib/WxPay.Api.php";
+
+/**
+ * 
+ * 刷卡支付实现类
+ * @author widyhu
+ *
+ */
+class NativePay
+{
+	/**
+	 * 
+	 * 生成扫描支付URL,模式一
+	 * @param BizPayUrlInput $bizUrlInfo
+	 */
+	public function GetPrePayUrl($productId)
+	{
+		$biz = new WxPayBizPayUrl();
+		$biz->SetProduct_id($productId);
+		$values = WxpayApi::bizpayurl($biz);
+		$url = "weixin://wxpay/bizpayurl?" . $this->ToUrlParams($values);
+		return $url;
+	}
+	
+	/**
+	 * 
+	 * 参数数组转换为url参数
+	 * @param array $urlObj
+	 */
+	private function ToUrlParams($urlObj)
+	{
+		$buff = "";
+		foreach ($urlObj as $k => $v)
+		{
+			$buff .= $k . "=" . $v . "&";
+		}
+		
+		$buff = trim($buff, "&");
+		return $buff;
+	}
+	
+	/**
+	 * 
+	 * 生成直接支付url,支付url有效期为2小时,模式二
+	 * @param UnifiedOrderInput $input
+	 */
+	public function GetPayUrl($input)
+	{
+		if($input->GetTrade_type() == "NATIVE")
+		{
+			$result = WxPayApi::unifiedOrder($input);
+			return $result;
+		}
+	}
+}

+ 40 - 0
extend/wxpay/example/download.php

@@ -0,0 +1,40 @@
+<?php
+require_once "../lib/WxPay.Api.php";
+//require_once "../lib/WxPay.MicroPay.php";
+
+
+if(isset($_REQUEST["bill_date"]) && $_REQUEST["bill_date"] != ""){
+	$bill_date = $_REQUEST["bill_date"];
+    $bill_type = $_REQUEST["bill_type"];
+	$input = new WxPayDownloadBill();
+	$input->SetBill_date($bill_date);
+	$input->SetBill_type($bill_type);
+	$file = WxPayApi::downloadBill($input);
+	echo $file;
+	//TODO 对账单文件处理
+    exit(0);
+}
+?>
+<html>
+<head>
+    <meta http-equiv="content-type" content="text/html;charset=utf-8"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1" /> 
+    <title>微信支付样例-查退款单</title>
+</head>
+<body>  
+	<form action="#" method="post">
+        <div style="margin-left:2%;">对账日期:</div><br/>
+        <input type="text" style="width:96%;height:35px;margin-left:2%;" name="bill_date" /><br /><br />
+        <div style="margin-left:2%;">账单类型:</div><br/>
+        <select style="width:96%;height:35px;margin-left:2%;" name="bill_type">
+		  <option value ="ALL">所有订单信息</option>
+		  <option value ="SUCCESS">成功支付的订单</option>
+		  <option value="REFUND">退款订单</option>
+		  <option value="REVOKED">撤销的订单</option>
+		</select><br /><br />
+       	<div align="center">
+			<input type="submit" value="下载订单" style="width:210px; height:50px; border-radius: 15px;background-color:#FE6714; border:0px #FE6714 solid; cursor: pointer;  color:white;  font-size:16px;" type="button" onclick="callpay()" />
+		</div>
+	</form>
+</body>
+</html>

+ 127 - 0
extend/wxpay/example/jsapi.php

@@ -0,0 +1,127 @@
+<?php 
+ini_set('date.timezone','Asia/Shanghai');
+//error_reporting(E_ERROR);
+require_once "../lib/WxPay.Api.php";
+require_once "WxPay.JsApiPay.php";
+require_once 'log.php';
+
+//初始化日志
+$logHandler= new CLogFileHandler("../logs/".date('Y-m-d').'.log');
+$log = Log::Init($logHandler, 15);
+
+//打印输出数组信息
+function printf_info($data)
+{
+    foreach($data as $key=>$value){
+        echo "<font color='#00ff55;'>$key</font> : $value <br/>";
+    }
+}
+
+//①、获取用户openid
+$tools = new JsApiPay();
+$openId = $tools->GetOpenid();
+
+//②、统一下单
+$input = new WxPayUnifiedOrder();
+$input->SetBody("test");
+$input->SetAttach("test");
+$input->SetOut_trade_no(WxPayConfig::MCHID.date("YmdHis"));
+$input->SetTotal_fee("1");
+$input->SetTime_start(date("YmdHis"));
+$input->SetTime_expire(date("YmdHis", time() + 600));
+$input->SetGoods_tag("test");
+$input->SetNotify_url("http://paysdk.weixin.qq.com/example/notify.php");
+$input->SetTrade_type("JSAPI");
+$input->SetOpenid($openId);
+$order = WxPayApi::unifiedOrder($input);
+echo '<font color="#f00"><b>统一下单支付单信息</b></font><br/>';
+printf_info($order);
+$jsApiParameters = $tools->GetJsApiParameters($order);
+
+//获取共享收货地址js函数参数
+$editAddress = $tools->GetEditAddressParameters();
+
+//③、在支持成功回调通知中处理成功之后的事宜,见 notify.php
+/**
+ * 注意:
+ * 1、当你的回调地址不可访问的时候,回调通知会失败,可以通过查询订单来确认支付是否成功
+ * 2、jsapi支付时需要填入用户openid,WxPay.JsApiPay.php中有获取openid流程 (文档可以参考微信公众平台“网页授权接口”,
+ * 参考http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html)
+ */
+?>
+
+<html>
+<head>
+    <meta http-equiv="content-type" content="text/html;charset=utf-8"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1"/> 
+    <title>微信支付样例-支付</title>
+    <script type="text/javascript">
+	//调用微信JS api 支付
+	function jsApiCall()
+	{
+		WeixinJSBridge.invoke(
+			'getBrandWCPayRequest',
+			<?php echo $jsApiParameters; ?>,
+			function(res){
+				WeixinJSBridge.log(res.err_msg);
+				alert(res.err_code+res.err_desc+res.err_msg);
+			}
+		);
+	}
+
+	function callpay()
+	{
+		if (typeof WeixinJSBridge == "undefined"){
+		    if( document.addEventListener ){
+		        document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);
+		    }else if (document.attachEvent){
+		        document.attachEvent('WeixinJSBridgeReady', jsApiCall); 
+		        document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
+		    }
+		}else{
+		    jsApiCall();
+		}
+	}
+	</script>
+	<script type="text/javascript">
+	//获取共享地址
+	function editAddress()
+	{
+		WeixinJSBridge.invoke(
+			'editAddress',
+			<?php echo $editAddress; ?>,
+			function(res){
+				var value1 = res.proviceFirstStageName;
+				var value2 = res.addressCitySecondStageName;
+				var value3 = res.addressCountiesThirdStageName;
+				var value4 = res.addressDetailInfo;
+				var tel = res.telNumber;
+				
+				alert(value1 + value2 + value3 + value4 + ":" + tel);
+			}
+		);
+	}
+	
+	window.onload = function(){
+		if (typeof WeixinJSBridge == "undefined"){
+		    if( document.addEventListener ){
+		        document.addEventListener('WeixinJSBridgeReady', editAddress, false);
+		    }else if (document.attachEvent){
+		        document.attachEvent('WeixinJSBridgeReady', editAddress); 
+		        document.attachEvent('onWeixinJSBridgeReady', editAddress);
+		    }
+		}else{
+			editAddress();
+		}
+	};
+	
+	</script>
+</head>
+<body>
+    <br/>
+    <font color="#9ACD32"><b>该笔订单支付金额为<span style="color:#f00;font-size:50px">1分</span>钱</b></font><br/><br/>
+	<div align="center">
+		<button style="width:210px; height:50px; border-radius: 15px;background-color:#FE6714; border:0px #FE6714 solid; cursor: pointer;  color:white;  font-size:16px;" type="button" onclick="callpay()" >立即支付</button>
+	</div>
+</body>
+</html>

+ 125 - 0
extend/wxpay/example/log.php

@@ -0,0 +1,125 @@
+<?php
+//以下为日志
+
+interface ILogHandler
+{
+	public function write($msg);
+	
+}
+
+class CLogFileHandler implements ILogHandler
+{
+	private $handle = null;
+	
+	public function __construct($file = '')
+	{
+		$this->handle = fopen($file,'a');
+	}
+	
+	public function write($msg)
+	{
+		fwrite($this->handle, $msg, 4096);
+	}
+	
+	public function __destruct()
+	{
+		fclose($this->handle);
+	}
+}
+
+class Log
+{
+	private $handler = null;
+	private $level = 15;
+	
+	private static $instance = null;
+	
+	private function __construct(){}
+
+	private function __clone(){}
+	
+	public static function Init($handler = null,$level = 15)
+	{
+		if(!self::$instance instanceof self)
+		{
+			self::$instance = new self();
+			self::$instance->__setHandle($handler);
+			self::$instance->__setLevel($level);
+		}
+		return self::$instance;
+	}
+	
+	
+	private function __setHandle($handler){
+		$this->handler = $handler;
+	}
+	
+	private function __setLevel($level)
+	{
+		$this->level = $level;
+	}
+	
+	public static function DEBUG($msg)
+	{
+		self::$instance->write(1, $msg);
+	}
+	
+	public static function WARN($msg)
+	{
+		self::$instance->write(4, $msg);
+	}
+	
+	public static function ERROR($msg)
+	{
+		$debugInfo = debug_backtrace();
+		$stack = "[";
+		foreach($debugInfo as $key => $val){
+			if(array_key_exists("file", $val)){
+				$stack .= ",file:" . $val["file"];
+			}
+			if(array_key_exists("line", $val)){
+				$stack .= ",line:" . $val["line"];
+			}
+			if(array_key_exists("function", $val)){
+				$stack .= ",function:" . $val["function"];
+			}
+		}
+		$stack .= "]";
+		self::$instance->write(8, $stack . $msg);
+	}
+	
+	public static function INFO($msg)
+	{
+		self::$instance->write(2, $msg);
+	}
+	
+	private function getLevelStr($level)
+	{
+		switch ($level)
+		{
+		case 1:
+			return 'debug';
+		break;
+		case 2:
+			return 'info';	
+		break;
+		case 4:
+			return 'warn';
+		break;
+		case 8:
+			return 'error';
+		break;
+		default:
+				
+		}
+	}
+	
+	protected function write($level,$msg)
+	{
+		if(($level & $this->level) == $level )
+		{
+			$msg = '['.date('Y-m-d H:i:s').']['.$this->getLevelStr($level).'] '.$msg."\n";
+			$this->handler->write($msg);
+		}
+	}
+}

+ 56 - 0
extend/wxpay/example/micropay.php

@@ -0,0 +1,56 @@
+<html>
+<head>
+    <meta http-equiv="content-type" content="text/html;charset=utf-8"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1" /> 
+    <title>微信支付样例-查退款单</title>
+</head>
+<?php
+require_once "../lib/WxPay.Api.php";
+require_once "WxPay.MicroPay.php";
+require_once 'log.php';
+
+//初始化日志
+$logHandler= new CLogFileHandler("../logs/".date('Y-m-d').'.log');
+$log = Log::Init($logHandler, 15);
+
+//打印输出数组信息
+function printf_info($data)
+{
+    foreach($data as $key=>$value){
+        echo "<font color='#00ff55;'>$key</font> : $value <br/>";
+    }
+}
+
+if(isset($_REQUEST["auth_code"]) && $_REQUEST["auth_code"] != ""){
+	$auth_code = $_REQUEST["auth_code"];
+	$input = new WxPayMicroPay();
+	$input->SetAuth_code($auth_code);
+	$input->SetBody("刷卡测试样例-支付");
+	$input->SetTotal_fee("1");
+	$input->SetOut_trade_no(WxPayConfig::MCHID.date("YmdHis"));
+	
+	$microPay = new MicroPay();
+	printf_info($microPay->pay($input));
+}
+
+/**
+ * 注意:
+ * 1、提交被扫之后,返回系统繁忙、用户输入密码等错误信息时需要循环查单以确定是否支付成功
+ * 2、多次(一半10次)确认都未明确成功时需要调用撤单接口撤单,防止用户重复支付
+ */
+
+?>
+<body>  
+	<form action="#" method="post">
+        <div style="margin-left:2%;">商品描述:</div><br/>
+        <input type="text" style="width:96%;height:35px;margin-left:2%;" readonly value="刷卡测试样例-支付" name="auth_code" /><br /><br />
+        <div style="margin-left:2%;">支付金额:</div><br/>
+        <input type="text" style="width:96%;height:35px;margin-left:2%;" readonly value="1分" name="auth_code" /><br /><br />
+        <div style="margin-left:2%;">授权码:</div><br/>
+        <input type="text" style="width:96%;height:35px;margin-left:2%;" name="auth_code" /><br /><br />
+       	<div align="center">
+			<input type="submit" value="提交刷卡" style="width:210px; height:50px; border-radius: 15px;background-color:#FE6714; border:0px #FE6714 solid; cursor: pointer;  color:white;  font-size:16px;" type="button" onclick="callpay()" />
+		</div>
+	</form>
+</body>
+</html>

+ 59 - 0
extend/wxpay/example/native.php

@@ -0,0 +1,59 @@
+<?php
+ini_set('date.timezone','Asia/Shanghai');
+//error_reporting(E_ERROR);
+
+require_once "../lib/WxPay.Api.php";
+require_once "WxPay.NativePay.php";
+require_once 'log.php';
+
+//模式一
+/**
+ * 流程:
+ * 1、组装包含支付信息的url,生成二维码
+ * 2、用户扫描二维码,进行支付
+ * 3、确定支付之后,微信服务器会回调预先配置的回调地址,在【微信开放平台-微信支付-支付配置】中进行配置
+ * 4、在接到回调通知之后,用户进行统一下单支付,并返回支付信息以完成支付(见:native_notify.php)
+ * 5、支付完成之后,微信服务器会通知支付成功
+ * 6、在支付成功通知中需要查单确认是否真正支付成功(见:notify.php)
+ */
+$notify = new NativePay();
+$url1 = $notify->GetPrePayUrl("123456789");
+
+//模式二
+/**
+ * 流程:
+ * 1、调用统一下单,取得code_url,生成二维码
+ * 2、用户扫描二维码,进行支付
+ * 3、支付完成之后,微信服务器会通知支付成功
+ * 4、在支付成功通知中需要查单确认是否真正支付成功(见:notify.php)
+ */
+$input = new WxPayUnifiedOrder();
+$input->SetBody("test");
+$input->SetAttach("test");
+$input->SetOut_trade_no(WxPayConfig::MCHID.date("YmdHis"));
+$input->SetTotal_fee("1");
+$input->SetTime_start(date("YmdHis"));
+$input->SetTime_expire(date("YmdHis", time() + 600));
+$input->SetGoods_tag("test");
+$input->SetNotify_url("http://paysdk.weixin.qq.com/example/notify.php");
+$input->SetTrade_type("NATIVE");
+$input->SetProduct_id("123456789");
+$result = $notify->GetPayUrl($input);
+$url2 = $result["code_url"];
+?>
+
+<html>
+<head>
+    <meta http-equiv="content-type" content="text/html;charset=utf-8"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1" /> 
+    <title>微信支付样例-退款</title>
+</head>
+<body>
+	<div style="margin-left: 10px;color:#556B2F;font-size:30px;font-weight: bolder;">扫描支付模式一</div><br/>
+	<img alt="模式一扫码支付" src="http://paysdk.weixin.qq.com/example/qrcode.php?data=<?php echo urlencode($url1);?>" style="width:150px;height:150px;"/>
+	<br/><br/><br/>
+	<div style="margin-left: 10px;color:#556B2F;font-size:30px;font-weight: bolder;">扫描支付模式二</div><br/>
+	<img alt="模式二扫码支付" src="http://paysdk.weixin.qq.com/example/qrcode.php?data=<?php echo urlencode($url2);?>" style="width:150px;height:150px;"/>
+	
+</body>
+</html>

+ 72 - 0
extend/wxpay/example/native_notify.php

@@ -0,0 +1,72 @@
+<?php
+ini_set('date.timezone','Asia/Shanghai');
+error_reporting(E_ERROR);
+
+require_once "../lib/WxPay.Api.php";
+require_once '../lib/WxPay.Notify.php';
+require_once 'log.php';
+
+//初始化日志
+$logHandler= new CLogFileHandler("../logs/".date('Y-m-d').'.log');
+$log = Log::Init($logHandler, 15);
+
+class NativeNotifyCallBack extends WxPayNotify
+{
+	public function unifiedorder($openId, $product_id)
+	{
+		//统一下单
+		$input = new WxPayUnifiedOrder();
+		$input->SetBody("test");
+		$input->SetAttach("test");
+		$input->SetOut_trade_no(WxPayConfig::MCHID.date("YmdHis"));
+		$input->SetTotal_fee("1");
+		$input->SetTime_start(date("YmdHis"));
+		$input->SetTime_expire(date("YmdHis", time() + 600));
+		$input->SetGoods_tag("test");
+		$input->SetNotify_url("http://paysdk.weixin.qq.com/example/notify.php");
+		$input->SetTrade_type("NATIVE");
+		$input->SetOpenid($openId);
+		$input->SetProduct_id($product_id);
+		$result = WxPayApi::unifiedOrder($input);
+		Log::DEBUG("unifiedorder:" . json_encode($result));
+		return $result;
+	}
+	
+	public function NotifyProcess($data, &$msg)
+	{
+		//echo "处理回调";
+		Log::DEBUG("call back:" . json_encode($data));
+		
+		if(!array_key_exists("openid", $data) ||
+			!array_key_exists("product_id", $data))
+		{
+			$msg = "回调数据异常";
+			return false;
+		}
+		 
+		$openid = $data["openid"];
+		$product_id = $data["product_id"];
+		
+		//统一下单
+		$result = $this->unifiedorder($openid, $product_id);
+		if(!array_key_exists("appid", $result) ||
+			 !array_key_exists("mch_id", $result) ||
+			 !array_key_exists("prepay_id", $result))
+		{
+		 	$msg = "统一下单失败";
+		 	return false;
+		 }
+		
+		$this->SetData("appid", $result["appid"]);
+		$this->SetData("mch_id", $result["mch_id"]);
+		$this->SetData("nonce_str", WxPayApi::getNonceStr());
+		$this->SetData("prepay_id", $result["prepay_id"]);
+		$this->SetData("result_code", "SUCCESS");
+		$this->SetData("err_code_des", "OK");
+		return true;
+	}
+}
+
+Log::DEBUG("begin notify!");
+$notify = new NativeNotifyCallBack();
+$notify->Handle(true);

+ 53 - 0
extend/wxpay/example/notify.php

@@ -0,0 +1,53 @@
+<?php
+ini_set('date.timezone','Asia/Shanghai');
+error_reporting(E_ERROR);
+
+require_once "../lib/WxPay.Api.php";
+require_once '../lib/WxPay.Notify.php';
+require_once 'log.php';
+
+//初始化日志
+$logHandler= new CLogFileHandler("../logs/".date('Y-m-d').'.log');
+$log = Log::Init($logHandler, 15);
+
+class PayNotifyCallBack extends WxPayNotify
+{
+	//查询订单
+	public function Queryorder($transaction_id)
+	{
+		$input = new WxPayOrderQuery();
+		$input->SetTransaction_id($transaction_id);
+		$result = WxPayApi::orderQuery($input);
+		Log::DEBUG("query:" . json_encode($result));
+		if(array_key_exists("return_code", $result)
+			&& array_key_exists("result_code", $result)
+			&& $result["return_code"] == "SUCCESS"
+			&& $result["result_code"] == "SUCCESS")
+		{
+			return true;
+		}
+		return false;
+	}
+	
+	//重写回调处理函数
+	public function NotifyProcess($data, &$msg)
+	{
+		Log::DEBUG("call back:" . json_encode($data));
+		$notfiyOutput = array();
+		
+		if(!array_key_exists("transaction_id", $data)){
+			$msg = "输入参数不正确";
+			return false;
+		}
+		//查询订单,判断订单真实性
+		if(!$this->Queryorder($data["transaction_id"])){
+			$msg = "订单查询失败";
+			return false;
+		}
+		return true;
+	}
+}
+
+Log::DEBUG("begin notify");
+$notify = new PayNotifyCallBack();
+$notify->Handle(false);

+ 53 - 0
extend/wxpay/example/orderquery.php

@@ -0,0 +1,53 @@
+<html>
+<head>
+    <meta http-equiv="content-type" content="text/html;charset=utf-8"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1" /> 
+    <title>微信支付样例-订单查询</title>
+</head>
+<?php
+ini_set('date.timezone','Asia/Shanghai');
+error_reporting(E_ERROR);
+require_once "../lib/WxPay.Api.php";
+require_once 'log.php';
+
+//初始化日志
+$logHandler= new CLogFileHandler("./logs/".date('Y-m-d').'.log');
+$log = Log::Init($logHandler, 15);
+
+function printf_info($data)
+{
+    foreach($data as $key=>$value){
+        echo "<font color='#f00;'>$key</font> : $value <br/>";
+    }
+}
+
+
+if(isset($_REQUEST["transaction_id"]) && $_REQUEST["transaction_id"] != ""){
+	$transaction_id = $_REQUEST["transaction_id"];
+	$input = new WxPayOrderQuery();
+	$input->SetTransaction_id($transaction_id);
+	printf_info(WxPayApi::orderQuery($input));
+	exit();
+}
+
+if(isset($_REQUEST["out_trade_no"]) && $_REQUEST["out_trade_no"] != ""){
+	$out_trade_no = $_REQUEST["out_trade_no"];
+	$input = new WxPayOrderQuery();
+	$input->SetOut_trade_no($out_trade_no);
+	printf_info(WxPayApi::orderQuery($input));
+	exit();
+}
+?>
+<body>  
+	<form action="#" method="post">
+        <div style="margin-left:2%;color:#f00">微信订单号和商户订单号选少填一个,微信订单号优先:</div><br/>
+        <div style="margin-left:2%;">微信订单号:</div><br/>
+        <input type="text" style="width:96%;height:35px;margin-left:2%;" name="transaction_id" /><br /><br />
+        <div style="margin-left:2%;">商户订单号:</div><br/>
+        <input type="text" style="width:96%;height:35px;margin-left:2%;" name="out_trade_no" /><br /><br />
+		<div align="center">
+			<input type="submit" value="查询" style="width:210px; height:50px; border-radius: 15px;background-color:#FE6714; border:0px #FE6714 solid; cursor: pointer;  color:white;  font-size:16px;" type="button" onclick="callpay()" />
+		</div>
+	</form>
+</body>
+</html>

+ 3312 - 0
extend/wxpay/example/phpqrcode/phpqrcode.php

@@ -0,0 +1,3312 @@
+<?php
+
+/*
+ * PHP QR Code encoder
+ *
+ * This file contains MERGED version of PHP QR Code library.
+ * It was auto-generated from full version for your convenience.
+ *
+ * This merged version was configured to not requre any external files,
+ * with disabled cache, error loging and weker but faster mask matching.
+ * If you need tune it up please use non-merged version.
+ *
+ * For full version, documentation, examples of use please visit:
+ *
+ *    http://phpqrcode.sourceforge.net/
+ *    https://sourceforge.net/projects/phpqrcode/
+ *
+ * PHP QR Code is distributed under LGPL 3
+ * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+ 
+ 
+
+/*
+ * Version: 1.1.4
+ * Build: 2010100721
+ */
+
+
+
+//---- qrconst.php -----------------------------
+
+
+
+
+
+/*
+ * PHP QR Code encoder
+ *
+ * Common constants
+ *
+ * Based on libqrencode C library distributed under LGPL 2.1
+ * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
+ *
+ * PHP QR Code is distributed under LGPL 3
+ * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+ 
+	// Encoding modes
+	 
+	define('QR_MODE_NUL', -1);
+	define('QR_MODE_NUM', 0);
+	define('QR_MODE_AN', 1);
+	define('QR_MODE_8', 2);
+	define('QR_MODE_KANJI', 3);
+	define('QR_MODE_STRUCTURE', 4);
+
+	// Levels of error correction.
+
+	define('QR_ECLEVEL_L', 0);
+	define('QR_ECLEVEL_M', 1);
+	define('QR_ECLEVEL_Q', 2);
+	define('QR_ECLEVEL_H', 3);
+	
+	// Supported output formats
+	
+	define('QR_FORMAT_TEXT', 0);
+	define('QR_FORMAT_PNG',  1);
+	
+	class qrstr {
+		public static function set(&$srctab, $x, $y, $repl, $replLen = false) {
+			$srctab[$y] = substr_replace($srctab[$y], ($replLen !== false)?substr($repl,0,$replLen):$repl, $x, ($replLen !== false)?$replLen:strlen($repl));
+		}
+	}	
+
+
+
+//---- merged_config.php -----------------------------
+
+
+
+
+/*
+ * PHP QR Code encoder
+ *
+ * Config file, tuned-up for merged verion
+ */
+     
+    define('QR_CACHEABLE', false);       // use cache - more disk reads but less CPU power, masks and format templates are stored there
+    define('QR_CACHE_DIR', false);       // used when QR_CACHEABLE === true
+    define('QR_LOG_DIR', false);         // default error logs dir   
+    
+    define('QR_FIND_BEST_MASK', true);                                                          // if true, estimates best mask (spec. default, but extremally slow; set to false to significant performance boost but (propably) worst quality code
+    define('QR_FIND_FROM_RANDOM', 2);                                                       // if false, checks all masks available, otherwise value tells count of masks need to be checked, mask id are got randomly
+    define('QR_DEFAULT_MASK', 2);                                                               // when QR_FIND_BEST_MASK === false
+                                                  
+    define('QR_PNG_MAXIMUM_SIZE',  1024);                                                       // maximum allowed png image width (in pixels), tune to make sure GD and PHP can handle such big images
+                                                  
+
+
+
+//---- qrtools.php -----------------------------
+
+
+
+
+/*
+ * PHP QR Code encoder
+ *
+ * Toolset, handy and debug utilites.
+ *
+ * PHP QR Code is distributed under LGPL 3
+ * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+    class QRtools {
+    
+        //----------------------------------------------------------------------
+        public static function binarize($frame)
+        {
+            $len = count($frame);
+            foreach ($frame as &$frameLine) {
+                
+                for($i=0; $i<$len; $i++) {
+                    $frameLine[$i] = (ord($frameLine[$i])&1)?'1':'0';
+                }
+            }
+            
+            return $frame;
+        }
+        
+        //----------------------------------------------------------------------
+        public static function tcpdfBarcodeArray($code, $mode = 'QR,L', $tcPdfVersion = '4.5.037')
+        {
+            $barcode_array = array();
+            
+            if (!is_array($mode))
+                $mode = explode(',', $mode);
+                
+            $eccLevel = 'L';
+                
+            if (count($mode) > 1) {
+                $eccLevel = $mode[1];
+            }
+                
+            $qrTab = QRcode::text($code, false, $eccLevel);
+            $size = count($qrTab);
+                
+            $barcode_array['num_rows'] = $size;
+            $barcode_array['num_cols'] = $size;
+            $barcode_array['bcode'] = array();
+                
+            foreach ($qrTab as $line) {
+                $arrAdd = array();
+                foreach(str_split($line) as $char)
+                    $arrAdd[] = ($char=='1')?1:0;
+                $barcode_array['bcode'][] = $arrAdd;
+            }
+                    
+            return $barcode_array;
+        }
+        
+        //----------------------------------------------------------------------
+        public static function clearCache()
+        {
+            self::$frames = array();
+        }
+        
+        //----------------------------------------------------------------------
+        public static function buildCache()
+        {
+			QRtools::markTime('before_build_cache');
+			
+			$mask = new QRmask();
+            for ($a=1; $a <= QRSPEC_VERSION_MAX; $a++) {
+                $frame = QRspec::newFrame($a);
+                if (QR_IMAGE) {
+                    $fileName = QR_CACHE_DIR.'frame_'.$a.'.png';
+                    QRimage::png(self::binarize($frame), $fileName, 1, 0);
+                }
+				
+				$width = count($frame);
+				$bitMask = array_fill(0, $width, array_fill(0, $width, 0));
+				for ($maskNo=0; $maskNo<8; $maskNo++)
+					$mask->makeMaskNo($maskNo, $width, $frame, $bitMask, true);
+            }
+			
+			QRtools::markTime('after_build_cache');
+        }
+
+        //----------------------------------------------------------------------
+        public static function log($outfile, $err)
+        {
+            if (QR_LOG_DIR !== false) {
+                if ($err != '') {
+                    if ($outfile !== false) {
+                        file_put_contents(QR_LOG_DIR.basename($outfile).'-errors.txt', date('Y-m-d H:i:s').': '.$err, FILE_APPEND);
+                    } else {
+                        file_put_contents(QR_LOG_DIR.'errors.txt', date('Y-m-d H:i:s').': '.$err, FILE_APPEND);
+                    }
+                }    
+            }
+        }
+        
+        //----------------------------------------------------------------------
+        public static function dumpMask($frame) 
+        {
+            $width = count($frame);
+            for($y=0;$y<$width;$y++) {
+                for($x=0;$x<$width;$x++) {
+                    echo ord($frame[$y][$x]).',';
+                }
+            }
+        }
+        
+        //----------------------------------------------------------------------
+        public static function markTime($markerId)
+        {
+            list($usec, $sec) = explode(" ", microtime());
+            $time = ((float)$usec + (float)$sec);
+            
+            if (!isset($GLOBALS['qr_time_bench']))
+                $GLOBALS['qr_time_bench'] = array();
+            
+            $GLOBALS['qr_time_bench'][$markerId] = $time;
+        }
+        
+        //----------------------------------------------------------------------
+        public static function timeBenchmark()
+        {
+            self::markTime('finish');
+        
+            $lastTime = 0;
+            $startTime = 0;
+            $p = 0;
+
+            echo '<table cellpadding="3" cellspacing="1">
+                    <thead><tr style="border-bottom:1px solid silver"><td colspan="2" style="text-align:center">BENCHMARK</td></tr></thead>
+                    <tbody>';
+
+            foreach($GLOBALS['qr_time_bench'] as $markerId=>$thisTime) {
+                if ($p > 0) {
+                    echo '<tr><th style="text-align:right">till '.$markerId.': </th><td>'.number_format($thisTime-$lastTime, 6).'s</td></tr>';
+                } else {
+                    $startTime = $thisTime;
+                }
+                
+                $p++;
+                $lastTime = $thisTime;
+            }
+            
+            echo '</tbody><tfoot>
+                <tr style="border-top:2px solid black"><th style="text-align:right">TOTAL: </th><td>'.number_format($lastTime-$startTime, 6).'s</td></tr>
+            </tfoot>
+            </table>';
+        }
+        
+    }
+    
+    //##########################################################################
+    
+    QRtools::markTime('start');
+    
+
+
+
+//---- qrspec.php -----------------------------
+
+
+
+
+/*
+ * PHP QR Code encoder
+ *
+ * QR Code specifications
+ *
+ * Based on libqrencode C library distributed under LGPL 2.1
+ * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
+ *
+ * PHP QR Code is distributed under LGPL 3
+ * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
+ *
+ * The following data / specifications are taken from
+ * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
+ *  or
+ * "Automatic identification and data capture techniques -- 
+ *  QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+ 
+    define('QRSPEC_VERSION_MAX', 40);
+    define('QRSPEC_WIDTH_MAX',   177);
+
+    define('QRCAP_WIDTH',        0);
+    define('QRCAP_WORDS',        1);
+    define('QRCAP_REMINDER',     2);
+    define('QRCAP_EC',           3);
+
+    class QRspec {
+    
+        public static $capacity = array(
+            array(  0,    0, 0, array(   0,    0,    0,    0)),
+            array( 21,   26, 0, array(   7,   10,   13,   17)), // 1
+            array( 25,   44, 7, array(  10,   16,   22,   28)),
+            array( 29,   70, 7, array(  15,   26,   36,   44)),
+            array( 33,  100, 7, array(  20,   36,   52,   64)),
+            array( 37,  134, 7, array(  26,   48,   72,   88)), // 5
+            array( 41,  172, 7, array(  36,   64,   96,  112)),
+            array( 45,  196, 0, array(  40,   72,  108,  130)),
+            array( 49,  242, 0, array(  48,   88,  132,  156)),
+            array( 53,  292, 0, array(  60,  110,  160,  192)),
+            array( 57,  346, 0, array(  72,  130,  192,  224)), //10
+            array( 61,  404, 0, array(  80,  150,  224,  264)),
+            array( 65,  466, 0, array(  96,  176,  260,  308)),
+            array( 69,  532, 0, array( 104,  198,  288,  352)),
+            array( 73,  581, 3, array( 120,  216,  320,  384)),
+            array( 77,  655, 3, array( 132,  240,  360,  432)), //15
+            array( 81,  733, 3, array( 144,  280,  408,  480)),
+            array( 85,  815, 3, array( 168,  308,  448,  532)),
+            array( 89,  901, 3, array( 180,  338,  504,  588)),
+            array( 93,  991, 3, array( 196,  364,  546,  650)),
+            array( 97, 1085, 3, array( 224,  416,  600,  700)), //20
+            array(101, 1156, 4, array( 224,  442,  644,  750)),
+            array(105, 1258, 4, array( 252,  476,  690,  816)),
+            array(109, 1364, 4, array( 270,  504,  750,  900)),
+            array(113, 1474, 4, array( 300,  560,  810,  960)),
+            array(117, 1588, 4, array( 312,  588,  870, 1050)), //25
+            array(121, 1706, 4, array( 336,  644,  952, 1110)),
+            array(125, 1828, 4, array( 360,  700, 1020, 1200)),
+            array(129, 1921, 3, array( 390,  728, 1050, 1260)),
+            array(133, 2051, 3, array( 420,  784, 1140, 1350)),
+            array(137, 2185, 3, array( 450,  812, 1200, 1440)), //30
+            array(141, 2323, 3, array( 480,  868, 1290, 1530)),
+            array(145, 2465, 3, array( 510,  924, 1350, 1620)),
+            array(149, 2611, 3, array( 540,  980, 1440, 1710)),
+            array(153, 2761, 3, array( 570, 1036, 1530, 1800)),
+            array(157, 2876, 0, array( 570, 1064, 1590, 1890)), //35
+            array(161, 3034, 0, array( 600, 1120, 1680, 1980)),
+            array(165, 3196, 0, array( 630, 1204, 1770, 2100)),
+            array(169, 3362, 0, array( 660, 1260, 1860, 2220)),
+            array(173, 3532, 0, array( 720, 1316, 1950, 2310)),
+            array(177, 3706, 0, array( 750, 1372, 2040, 2430)) //40
+        );
+        
+        //----------------------------------------------------------------------
+        public static function getDataLength($version, $level)
+        {
+            return self::$capacity[$version][QRCAP_WORDS] - self::$capacity[$version][QRCAP_EC][$level];
+        }
+        
+        //----------------------------------------------------------------------
+        public static function getECCLength($version, $level)
+        {
+            return self::$capacity[$version][QRCAP_EC][$level];
+        }
+        
+        //----------------------------------------------------------------------
+        public static function getWidth($version)
+        {
+            return self::$capacity[$version][QRCAP_WIDTH];
+        }
+        
+        //----------------------------------------------------------------------
+        public static function getRemainder($version)
+        {
+            return self::$capacity[$version][QRCAP_REMINDER];
+        }
+        
+        //----------------------------------------------------------------------
+        public static function getMinimumVersion($size, $level)
+        {
+
+            for($i=1; $i<= QRSPEC_VERSION_MAX; $i++) {
+                $words  = self::$capacity[$i][QRCAP_WORDS] - self::$capacity[$i][QRCAP_EC][$level];
+                if($words >= $size) 
+                    return $i;
+            }
+
+            return -1;
+        }
+    
+        //######################################################################
+        
+        public static $lengthTableBits = array(
+            array(10, 12, 14),
+            array( 9, 11, 13),
+            array( 8, 16, 16),
+            array( 8, 10, 12)
+        );
+        
+        //----------------------------------------------------------------------
+        public static function lengthIndicator($mode, $version)
+        {
+            if ($mode == QR_MODE_STRUCTURE)
+                return 0;
+                
+            if ($version <= 9) {
+                $l = 0;
+            } else if ($version <= 26) {
+                $l = 1;
+            } else {
+                $l = 2;
+            }
+
+            return self::$lengthTableBits[$mode][$l];
+        }
+        
+        //----------------------------------------------------------------------
+        public static function maximumWords($mode, $version)
+        {
+            if($mode == QR_MODE_STRUCTURE) 
+                return 3;
+                
+            if($version <= 9) {
+                $l = 0;
+            } else if($version <= 26) {
+                $l = 1;
+            } else {
+                $l = 2;
+            }
+
+            $bits = self::$lengthTableBits[$mode][$l];
+            $words = (1 << $bits) - 1;
+            
+            if($mode == QR_MODE_KANJI) {
+                $words *= 2; // the number of bytes is required
+            }
+
+            return $words;
+        }
+
+        // Error correction code -----------------------------------------------
+        // Table of the error correction code (Reed-Solomon block)
+        // See Table 12-16 (pp.30-36), JIS X0510:2004.
+
+        public static $eccTable = array(
+            array(array( 0,  0), array( 0,  0), array( 0,  0), array( 0,  0)),
+            array(array( 1,  0), array( 1,  0), array( 1,  0), array( 1,  0)), // 1
+            array(array( 1,  0), array( 1,  0), array( 1,  0), array( 1,  0)),
+            array(array( 1,  0), array( 1,  0), array( 2,  0), array( 2,  0)),
+            array(array( 1,  0), array( 2,  0), array( 2,  0), array( 4,  0)),
+            array(array( 1,  0), array( 2,  0), array( 2,  2), array( 2,  2)), // 5
+            array(array( 2,  0), array( 4,  0), array( 4,  0), array( 4,  0)),
+            array(array( 2,  0), array( 4,  0), array( 2,  4), array( 4,  1)),
+            array(array( 2,  0), array( 2,  2), array( 4,  2), array( 4,  2)),
+            array(array( 2,  0), array( 3,  2), array( 4,  4), array( 4,  4)),
+            array(array( 2,  2), array( 4,  1), array( 6,  2), array( 6,  2)), //10
+            array(array( 4,  0), array( 1,  4), array( 4,  4), array( 3,  8)),
+            array(array( 2,  2), array( 6,  2), array( 4,  6), array( 7,  4)),
+            array(array( 4,  0), array( 8,  1), array( 8,  4), array(12,  4)),
+            array(array( 3,  1), array( 4,  5), array(11,  5), array(11,  5)),
+            array(array( 5,  1), array( 5,  5), array( 5,  7), array(11,  7)), //15
+            array(array( 5,  1), array( 7,  3), array(15,  2), array( 3, 13)),
+            array(array( 1,  5), array(10,  1), array( 1, 15), array( 2, 17)),
+            array(array( 5,  1), array( 9,  4), array(17,  1), array( 2, 19)),
+            array(array( 3,  4), array( 3, 11), array(17,  4), array( 9, 16)),
+            array(array( 3,  5), array( 3, 13), array(15,  5), array(15, 10)), //20
+            array(array( 4,  4), array(17,  0), array(17,  6), array(19,  6)),
+            array(array( 2,  7), array(17,  0), array( 7, 16), array(34,  0)),
+            array(array( 4,  5), array( 4, 14), array(11, 14), array(16, 14)),
+            array(array( 6,  4), array( 6, 14), array(11, 16), array(30,  2)),
+            array(array( 8,  4), array( 8, 13), array( 7, 22), array(22, 13)), //25
+            array(array(10,  2), array(19,  4), array(28,  6), array(33,  4)),
+            array(array( 8,  4), array(22,  3), array( 8, 26), array(12, 28)),
+            array(array( 3, 10), array( 3, 23), array( 4, 31), array(11, 31)),
+            array(array( 7,  7), array(21,  7), array( 1, 37), array(19, 26)),
+            array(array( 5, 10), array(19, 10), array(15, 25), array(23, 25)), //30
+            array(array(13,  3), array( 2, 29), array(42,  1), array(23, 28)),
+            array(array(17,  0), array(10, 23), array(10, 35), array(19, 35)),
+            array(array(17,  1), array(14, 21), array(29, 19), array(11, 46)),
+            array(array(13,  6), array(14, 23), array(44,  7), array(59,  1)),
+            array(array(12,  7), array(12, 26), array(39, 14), array(22, 41)), //35
+            array(array( 6, 14), array( 6, 34), array(46, 10), array( 2, 64)),
+            array(array(17,  4), array(29, 14), array(49, 10), array(24, 46)),
+            array(array( 4, 18), array(13, 32), array(48, 14), array(42, 32)),
+            array(array(20,  4), array(40,  7), array(43, 22), array(10, 67)),
+            array(array(19,  6), array(18, 31), array(34, 34), array(20, 61)),//40
+        );                                                                       
+
+        //----------------------------------------------------------------------
+        // CACHEABLE!!!
+        
+        public static function getEccSpec($version, $level, array &$spec)
+        {
+            if (count($spec) < 5) {
+                $spec = array(0,0,0,0,0);
+            }
+
+            $b1   = self::$eccTable[$version][$level][0];
+            $b2   = self::$eccTable[$version][$level][1];
+            $data = self::getDataLength($version, $level);
+            $ecc  = self::getECCLength($version, $level);
+
+            if($b2 == 0) {
+                $spec[0] = $b1;
+                $spec[1] = (int)($data / $b1);
+                $spec[2] = (int)($ecc / $b1);
+                $spec[3] = 0; 
+                $spec[4] = 0;
+            } else {
+                $spec[0] = $b1;
+                $spec[1] = (int)($data / ($b1 + $b2));
+                $spec[2] = (int)($ecc  / ($b1 + $b2));
+                $spec[3] = $b2;
+                $spec[4] = $spec[1] + 1;
+            }
+        }
+
+        // Alignment pattern ---------------------------------------------------
+
+        // Positions of alignment patterns.
+        // This array includes only the second and the third position of the 
+        // alignment patterns. Rest of them can be calculated from the distance 
+        // between them.
+         
+        // See Table 1 in Appendix E (pp.71) of JIS X0510:2004.
+         
+        public static $alignmentPattern = array(      
+            array( 0,  0),
+            array( 0,  0), array(18,  0), array(22,  0), array(26,  0), array(30,  0), // 1- 5
+            array(34,  0), array(22, 38), array(24, 42), array(26, 46), array(28, 50), // 6-10
+            array(30, 54), array(32, 58), array(34, 62), array(26, 46), array(26, 48), //11-15
+            array(26, 50), array(30, 54), array(30, 56), array(30, 58), array(34, 62), //16-20
+            array(28, 50), array(26, 50), array(30, 54), array(28, 54), array(32, 58), //21-25
+            array(30, 58), array(34, 62), array(26, 50), array(30, 54), array(26, 52), //26-30
+            array(30, 56), array(34, 60), array(30, 58), array(34, 62), array(30, 54), //31-35
+            array(24, 50), array(28, 54), array(32, 58), array(26, 54), array(30, 58), //35-40
+        );                                                                                  
+
+        
+        /** --------------------------------------------------------------------
+         * Put an alignment marker.
+         * @param frame
+         * @param width
+         * @param ox,oy center coordinate of the pattern
+         */
+        public static function putAlignmentMarker(array &$frame, $ox, $oy)
+        {
+            $finder = array(
+                "\xa1\xa1\xa1\xa1\xa1",
+                "\xa1\xa0\xa0\xa0\xa1",
+                "\xa1\xa0\xa1\xa0\xa1",
+                "\xa1\xa0\xa0\xa0\xa1",
+                "\xa1\xa1\xa1\xa1\xa1"
+            );                        
+            
+            $yStart = $oy-2;         
+            $xStart = $ox-2;
+            
+            for($y=0; $y<5; $y++) {
+                QRstr::set($frame, $xStart, $yStart+$y, $finder[$y]);
+            }
+        }
+
+        //----------------------------------------------------------------------
+        public static function putAlignmentPattern($version, &$frame, $width)
+        {
+            if($version < 2)
+                return;
+
+            $d = self::$alignmentPattern[$version][1] - self::$alignmentPattern[$version][0];
+            if($d < 0) {
+                $w = 2;
+            } else {
+                $w = (int)(($width - self::$alignmentPattern[$version][0]) / $d + 2);
+            }
+
+            if($w * $w - 3 == 1) {
+                $x = self::$alignmentPattern[$version][0];
+                $y = self::$alignmentPattern[$version][0];
+                self::putAlignmentMarker($frame, $x, $y);
+                return;
+            }
+
+            $cx = self::$alignmentPattern[$version][0];
+            for($x=1; $x<$w - 1; $x++) {
+                self::putAlignmentMarker($frame, 6, $cx);
+                self::putAlignmentMarker($frame, $cx,  6);
+                $cx += $d;
+            }
+
+            $cy = self::$alignmentPattern[$version][0];
+            for($y=0; $y<$w-1; $y++) {
+                $cx = self::$alignmentPattern[$version][0];
+                for($x=0; $x<$w-1; $x++) {
+                    self::putAlignmentMarker($frame, $cx, $cy);
+                    $cx += $d;
+                }
+                $cy += $d;
+            }
+        }
+
+        // Version information pattern -----------------------------------------
+
+		// Version information pattern (BCH coded).
+        // See Table 1 in Appendix D (pp.68) of JIS X0510:2004.
+        
+		// size: [QRSPEC_VERSION_MAX - 6]
+		
+        public static $versionPattern = array(
+            0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d,
+            0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9,
+            0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75,
+            0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64,
+            0x27541, 0x28c69
+        );
+
+        //----------------------------------------------------------------------
+        public static function getVersionPattern($version)
+        {
+            if($version < 7 || $version > QRSPEC_VERSION_MAX)
+                return 0;
+
+            return self::$versionPattern[$version -7];
+        }
+
+        // Format information --------------------------------------------------
+        // See calcFormatInfo in tests/test_qrspec.c (orginal qrencode c lib)
+        
+        public static $formatInfo = array(
+            array(0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976),
+            array(0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0),
+            array(0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed),
+            array(0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b)
+        );
+
+        public static function getFormatInfo($mask, $level)
+        {
+            if($mask < 0 || $mask > 7)
+                return 0;
+                
+            if($level < 0 || $level > 3)
+                return 0;                
+
+            return self::$formatInfo[$level][$mask];
+        }
+
+        // Frame ---------------------------------------------------------------
+        // Cache of initial frames.
+         
+        public static $frames = array();
+
+        /** --------------------------------------------------------------------
+         * Put a finder pattern.
+         * @param frame
+         * @param width
+         * @param ox,oy upper-left coordinate of the pattern
+         */
+        public static function putFinderPattern(&$frame, $ox, $oy)
+        {
+            $finder = array(
+                "\xc1\xc1\xc1\xc1\xc1\xc1\xc1",
+                "\xc1\xc0\xc0\xc0\xc0\xc0\xc1",
+                "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
+                "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
+                "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
+                "\xc1\xc0\xc0\xc0\xc0\xc0\xc1",
+                "\xc1\xc1\xc1\xc1\xc1\xc1\xc1"
+            );                            
+            
+            for($y=0; $y<7; $y++) {
+                QRstr::set($frame, $ox, $oy+$y, $finder[$y]);
+            }
+        }
+
+        //----------------------------------------------------------------------
+        public static function createFrame($version)
+        {
+            $width = self::$capacity[$version][QRCAP_WIDTH];
+            $frameLine = str_repeat ("\0", $width);
+            $frame = array_fill(0, $width, $frameLine);
+
+            // Finder pattern
+            self::putFinderPattern($frame, 0, 0);
+            self::putFinderPattern($frame, $width - 7, 0);
+            self::putFinderPattern($frame, 0, $width - 7);
+            
+            // Separator
+            $yOffset = $width - 7;
+            
+            for($y=0; $y<7; $y++) {
+                $frame[$y][7] = "\xc0";
+                $frame[$y][$width - 8] = "\xc0";
+                $frame[$yOffset][7] = "\xc0";
+                $yOffset++;
+            }
+            
+            $setPattern = str_repeat("\xc0", 8);
+            
+            QRstr::set($frame, 0, 7, $setPattern);
+            QRstr::set($frame, $width-8, 7, $setPattern);
+            QRstr::set($frame, 0, $width - 8, $setPattern);
+        
+            // Format info
+            $setPattern = str_repeat("\x84", 9);
+            QRstr::set($frame, 0, 8, $setPattern);
+            QRstr::set($frame, $width - 8, 8, $setPattern, 8);
+            
+            $yOffset = $width - 8;
+
+            for($y=0; $y<8; $y++,$yOffset++) {
+                $frame[$y][8] = "\x84";
+                $frame[$yOffset][8] = "\x84";
+            }
+
+            // Timing pattern  
+            
+            for($i=1; $i<$width-15; $i++) {
+                $frame[6][7+$i] = chr(0x90 | ($i & 1));
+                $frame[7+$i][6] = chr(0x90 | ($i & 1));
+            }
+            
+            // Alignment pattern  
+            self::putAlignmentPattern($version, $frame, $width);
+            
+            // Version information 
+            if($version >= 7) {
+                $vinf = self::getVersionPattern($version);
+
+                $v = $vinf;
+                
+                for($x=0; $x<6; $x++) {
+                    for($y=0; $y<3; $y++) {
+                        $frame[($width - 11)+$y][$x] = chr(0x88 | ($v & 1));
+                        $v = $v >> 1;
+                    }
+                }
+
+                $v = $vinf;
+                for($y=0; $y<6; $y++) {
+                    for($x=0; $x<3; $x++) {
+                        $frame[$y][$x+($width - 11)] = chr(0x88 | ($v & 1));
+                        $v = $v >> 1;
+                    }
+                }
+            }
+    
+            // and a little bit...  
+            $frame[$width - 8][8] = "\x81";
+            
+            return $frame;
+        }
+
+        //----------------------------------------------------------------------
+        public static function debug($frame, $binary_mode = false)
+        {
+            if ($binary_mode) {
+            
+                    foreach ($frame as &$frameLine) {
+                        $frameLine = join('<span class="m">&nbsp;&nbsp;</span>', explode('0', $frameLine));
+                        $frameLine = join('&#9608;&#9608;', explode('1', $frameLine));
+                    }
+                    
+                    ?>
+                <style>
+                    .m { background-color: white; }
+                </style>
+                <?php
+                    echo '<pre><tt><br/ ><br/ ><br/ >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
+                    echo join("<br/ >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;", $frame);
+                    echo '</tt></pre><br/ ><br/ ><br/ ><br/ ><br/ ><br/ >';
+            
+            } else {
+            
+                foreach ($frame as &$frameLine) {
+                    $frameLine = join('<span class="m">&nbsp;</span>',  explode("\xc0", $frameLine));
+                    $frameLine = join('<span class="m">&#9618;</span>', explode("\xc1", $frameLine));
+                    $frameLine = join('<span class="p">&nbsp;</span>',  explode("\xa0", $frameLine));
+                    $frameLine = join('<span class="p">&#9618;</span>', explode("\xa1", $frameLine));
+                    $frameLine = join('<span class="s">&#9671;</span>', explode("\x84", $frameLine)); //format 0
+                    $frameLine = join('<span class="s">&#9670;</span>', explode("\x85", $frameLine)); //format 1
+                    $frameLine = join('<span class="x">&#9762;</span>', explode("\x81", $frameLine)); //special bit
+                    $frameLine = join('<span class="c">&nbsp;</span>',  explode("\x90", $frameLine)); //clock 0
+                    $frameLine = join('<span class="c">&#9719;</span>', explode("\x91", $frameLine)); //clock 1
+                    $frameLine = join('<span class="f">&nbsp;</span>',  explode("\x88", $frameLine)); //version
+                    $frameLine = join('<span class="f">&#9618;</span>', explode("\x89", $frameLine)); //version
+                    $frameLine = join('&#9830;', explode("\x01", $frameLine));
+                    $frameLine = join('&#8901;', explode("\0", $frameLine));
+                }
+                
+                ?>
+                <style>
+                    .p { background-color: yellow; }
+                    .m { background-color: #00FF00; }
+                    .s { background-color: #FF0000; }
+                    .c { background-color: aqua; }
+                    .x { background-color: pink; }
+                    .f { background-color: gold; }
+                </style>
+                <?php
+                echo "<pre><tt>";
+                echo join("<br/ >", $frame);
+                echo "</tt></pre>";
+            
+            }
+        }
+
+        //----------------------------------------------------------------------
+        public static function serial($frame)
+        {
+            return gzcompress(join("\n", $frame), 9);
+        }
+        
+        //----------------------------------------------------------------------
+        public static function unserial($code)
+        {
+            return explode("\n", gzuncompress($code));
+        }
+        
+        //----------------------------------------------------------------------
+        public static function newFrame($version)
+        {
+            if($version < 1 || $version > QRSPEC_VERSION_MAX) 
+                return null;
+
+            if(!isset(self::$frames[$version])) {
+                
+                $fileName = QR_CACHE_DIR.'frame_'.$version.'.dat';
+                
+                if (QR_CACHEABLE) {
+                    if (file_exists($fileName)) {
+                        self::$frames[$version] = self::unserial(file_get_contents($fileName));
+                    } else {
+                        self::$frames[$version] = self::createFrame($version);
+                        file_put_contents($fileName, self::serial(self::$frames[$version]));
+                    }
+                } else {
+                    self::$frames[$version] = self::createFrame($version);
+                }
+            }
+            
+            if(is_null(self::$frames[$version]))
+                return null;
+
+            return self::$frames[$version];
+        }
+
+        //----------------------------------------------------------------------
+        public static function rsBlockNum($spec)     { return $spec[0] + $spec[3]; }
+        public static function rsBlockNum1($spec)    { return $spec[0]; }
+        public static function rsDataCodes1($spec)   { return $spec[1]; }
+        public static function rsEccCodes1($spec)    { return $spec[2]; }
+        public static function rsBlockNum2($spec)    { return $spec[3]; }
+        public static function rsDataCodes2($spec)   { return $spec[4]; }
+        public static function rsEccCodes2($spec)    { return $spec[2]; }
+        public static function rsDataLength($spec)   { return ($spec[0] * $spec[1]) + ($spec[3] * $spec[4]);    }
+        public static function rsEccLength($spec)    { return ($spec[0] + $spec[3]) * $spec[2]; }
+        
+    }
+
+
+
+//---- qrimage.php -----------------------------
+
+
+
+
+/*
+ * PHP QR Code encoder
+ *
+ * Image output of code using GD2
+ *
+ * PHP QR Code is distributed under LGPL 3
+ * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+ 
+    define('QR_IMAGE', true);
+
+    class QRimage {
+    
+        //----------------------------------------------------------------------
+        public static function png($frame, $filename = false, $pixelPerPoint = 4, $outerFrame = 4,$saveandprint=FALSE) 
+        {
+            $image = self::image($frame, $pixelPerPoint, $outerFrame);
+            
+            if ($filename === false) {
+                Header("Content-type: image/png");
+                ImagePng($image);
+            } else {
+                if($saveandprint===TRUE){
+                    ImagePng($image, $filename);
+                    header("Content-type: image/png");
+                    ImagePng($image);
+                }else{
+                    ImagePng($image, $filename);
+                }
+            }
+            
+            ImageDestroy($image);
+        }
+    
+        //----------------------------------------------------------------------
+        public static function jpg($frame, $filename = false, $pixelPerPoint = 8, $outerFrame = 4, $q = 85) 
+        {
+            $image = self::image($frame, $pixelPerPoint, $outerFrame);
+            
+            if ($filename === false) {
+                Header("Content-type: image/jpeg");
+                ImageJpeg($image, null, $q);
+            } else {
+                ImageJpeg($image, $filename, $q);            
+            }
+            
+            ImageDestroy($image);
+        }
+    
+        //----------------------------------------------------------------------
+        private static function image($frame, $pixelPerPoint = 4, $outerFrame = 4) 
+        {
+            $h = count($frame);
+            $w = strlen($frame[0]);
+            
+            $imgW = $w + 2*$outerFrame;
+            $imgH = $h + 2*$outerFrame;
+            
+            $base_image =ImageCreate($imgW, $imgH);
+            
+            $col[0] = ImageColorAllocate($base_image,255,255,255);
+            $col[1] = ImageColorAllocate($base_image,0,0,0);
+
+            imagefill($base_image, 0, 0, $col[0]);
+
+            for($y=0; $y<$h; $y++) {
+                for($x=0; $x<$w; $x++) {
+                    if ($frame[$y][$x] == '1') {
+                        ImageSetPixel($base_image,$x+$outerFrame,$y+$outerFrame,$col[1]); 
+                    }
+                }
+            }
+            
+            $target_image =ImageCreate($imgW * $pixelPerPoint, $imgH * $pixelPerPoint);
+            ImageCopyResized($target_image, $base_image, 0, 0, 0, 0, $imgW * $pixelPerPoint, $imgH * $pixelPerPoint, $imgW, $imgH);
+            ImageDestroy($base_image);
+            
+            return $target_image;
+        }
+    }
+
+
+
+//---- qrinput.php -----------------------------
+
+
+
+
+/*
+ * PHP QR Code encoder
+ *
+ * Input encoding class
+ *
+ * Based on libqrencode C library distributed under LGPL 2.1
+ * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
+ *
+ * PHP QR Code is distributed under LGPL 3
+ * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+ 
+    define('STRUCTURE_HEADER_BITS',  20);
+    define('MAX_STRUCTURED_SYMBOLS', 16);
+
+    class QRinputItem {
+    
+        public $mode;
+        public $size;
+        public $data;
+        public $bstream;
+
+        public function __construct($mode, $size, $data, $bstream = null) 
+        {
+            $setData = array_slice($data, 0, $size);
+            
+            if (count($setData) < $size) {
+                $setData = array_merge($setData, array_fill(0,$size-count($setData),0));
+            }
+        
+            if(!QRinput::check($mode, $size, $setData)) {
+                throw new Exception('Error m:'.$mode.',s:'.$size.',d:'.join(',',$setData));
+                return null;
+            }
+            
+            $this->mode = $mode;
+            $this->size = $size;
+            $this->data = $setData;
+            $this->bstream = $bstream;
+        }
+        
+        //----------------------------------------------------------------------
+        public function encodeModeNum($version)
+        {
+            try {
+            
+                $words = (int)($this->size / 3);
+                $bs = new QRbitstream();
+                
+                $val = 0x1;
+                $bs->appendNum(4, $val);
+                $bs->appendNum(QRspec::lengthIndicator(QR_MODE_NUM, $version), $this->size);
+
+                for($i=0; $i<$words; $i++) {
+                    $val  = (ord($this->data[$i*3  ]) - ord('0')) * 100;
+                    $val += (ord($this->data[$i*3+1]) - ord('0')) * 10;
+                    $val += (ord($this->data[$i*3+2]) - ord('0'));
+                    $bs->appendNum(10, $val);
+                }
+
+                if($this->size - $words * 3 == 1) {
+                    $val = ord($this->data[$words*3]) - ord('0');
+                    $bs->appendNum(4, $val);
+                } else if($this->size - $words * 3 == 2) {
+                    $val  = (ord($this->data[$words*3  ]) - ord('0')) * 10;
+                    $val += (ord($this->data[$words*3+1]) - ord('0'));
+                    $bs->appendNum(7, $val);
+                }
+
+                $this->bstream = $bs;
+                return 0;
+                
+            } catch (Exception $e) {
+                return -1;
+            }
+        }
+        
+        //----------------------------------------------------------------------
+        public function encodeModeAn($version)
+        {
+            try {
+                $words = (int)($this->size / 2);
+                $bs = new QRbitstream();
+                
+                $bs->appendNum(4, 0x02);
+                $bs->appendNum(QRspec::lengthIndicator(QR_MODE_AN, $version), $this->size);
+
+                for($i=0; $i<$words; $i++) {
+                    $val  = (int)QRinput::lookAnTable(ord($this->data[$i*2  ])) * 45;
+                    $val += (int)QRinput::lookAnTable(ord($this->data[$i*2+1]));
+
+                    $bs->appendNum(11, $val);
+                }
+
+                if($this->size & 1) {
+                    $val = QRinput::lookAnTable(ord($this->data[$words * 2]));
+                    $bs->appendNum(6, $val);
+                }
+        
+                $this->bstream = $bs;
+                return 0;
+            
+            } catch (Exception $e) {
+                return -1;
+            }
+        }
+        
+        //----------------------------------------------------------------------
+        public function encodeMode8($version)
+        {
+            try {
+                $bs = new QRbitstream();
+
+                $bs->appendNum(4, 0x4);
+                $bs->appendNum(QRspec::lengthIndicator(QR_MODE_8, $version), $this->size);
+
+                for($i=0; $i<$this->size; $i++) {
+                    $bs->appendNum(8, ord($this->data[$i]));
+                }
+
+                $this->bstream = $bs;
+                return 0;
+            
+            } catch (Exception $e) {
+                return -1;
+            }
+        }
+        
+        //----------------------------------------------------------------------
+        public function encodeModeKanji($version)
+        {
+            try {
+
+                $bs = new QRbitrtream();
+                
+                $bs->appendNum(4, 0x8);
+                $bs->appendNum(QRspec::lengthIndicator(QR_MODE_KANJI, $version), (int)($this->size / 2));
+
+                for($i=0; $i<$this->size; $i+=2) {
+                    $val = (ord($this->data[$i]) << 8) | ord($this->data[$i+1]);
+                    if($val <= 0x9ffc) {
+                        $val -= 0x8140;
+                    } else {
+                        $val -= 0xc140;
+                    }
+                    
+                    $h = ($val >> 8) * 0xc0;
+                    $val = ($val & 0xff) + $h;
+
+                    $bs->appendNum(13, $val);
+                }
+
+                $this->bstream = $bs;
+                return 0;
+            
+            } catch (Exception $e) {
+                return -1;
+            }
+        }
+
+        //----------------------------------------------------------------------
+        public function encodeModeStructure()
+        {
+            try {
+                $bs =  new QRbitstream();
+                
+                $bs->appendNum(4, 0x03);
+                $bs->appendNum(4, ord($this->data[1]) - 1);
+                $bs->appendNum(4, ord($this->data[0]) - 1);
+                $bs->appendNum(8, ord($this->data[2]));
+
+                $this->bstream = $bs;
+                return 0;
+            
+            } catch (Exception $e) {
+                return -1;
+            }
+        }
+        
+        //----------------------------------------------------------------------
+        public function estimateBitStreamSizeOfEntry($version)
+        {
+            $bits = 0;
+
+            if($version == 0) 
+                $version = 1;
+
+            switch($this->mode) {
+                case QR_MODE_NUM:        $bits = QRinput::estimateBitsModeNum($this->size);    break;
+                case QR_MODE_AN:        $bits = QRinput::estimateBitsModeAn($this->size);    break;
+                case QR_MODE_8:            $bits = QRinput::estimateBitsMode8($this->size);    break;
+                case QR_MODE_KANJI:        $bits = QRinput::estimateBitsModeKanji($this->size);break;
+                case QR_MODE_STRUCTURE:    return STRUCTURE_HEADER_BITS;            
+                default:
+                    return 0;
+            }
+
+            $l = QRspec::lengthIndicator($this->mode, $version);
+            $m = 1 << $l;
+            $num = (int)(($this->size + $m - 1) / $m);
+
+            $bits += $num * (4 + $l);
+
+            return $bits;
+        }
+        
+        //----------------------------------------------------------------------
+        public function encodeBitStream($version)
+        {
+            try {
+            
+                unset($this->bstream);
+                $words = QRspec::maximumWords($this->mode, $version);
+                
+                if($this->size > $words) {
+                
+                    $st1 = new QRinputItem($this->mode, $words, $this->data);
+                    $st2 = new QRinputItem($this->mode, $this->size - $words, array_slice($this->data, $words));
+
+                    $st1->encodeBitStream($version);
+                    $st2->encodeBitStream($version);
+                    
+                    $this->bstream = new QRbitstream();
+                    $this->bstream->append($st1->bstream);
+                    $this->bstream->append($st2->bstream);
+                    
+                    unset($st1);
+                    unset($st2);
+                    
+                } else {
+                    
+                    $ret = 0;
+                    
+                    switch($this->mode) {
+                        case QR_MODE_NUM:        $ret = $this->encodeModeNum($version);    break;
+                        case QR_MODE_AN:        $ret = $this->encodeModeAn($version);    break;
+                        case QR_MODE_8:            $ret = $this->encodeMode8($version);    break;
+                        case QR_MODE_KANJI:        $ret = $this->encodeModeKanji($version);break;
+                        case QR_MODE_STRUCTURE:    $ret = $this->encodeModeStructure();    break;
+                        
+                        default:
+                            break;
+                    }
+                    
+                    if($ret < 0)
+                        return -1;
+                }
+
+                return $this->bstream->size();
+            
+            } catch (Exception $e) {
+                return -1;
+            }
+        }
+    };
+    
+    //##########################################################################
+
+    class QRinput {
+
+        public $items;
+        
+        private $version;
+        private $level;
+        
+        //----------------------------------------------------------------------
+        public function __construct($version = 0, $level = QR_ECLEVEL_L)
+        {
+            if ($version < 0 || $version > QRSPEC_VERSION_MAX || $level > QR_ECLEVEL_H) {
+                throw new Exception('Invalid version no');
+                return NULL;
+            }
+            
+            $this->version = $version;
+            $this->level = $level;
+        }
+        
+        //----------------------------------------------------------------------
+        public function getVersion()
+        {
+            return $this->version;
+        }
+        
+        //----------------------------------------------------------------------
+        public function setVersion($version)
+        {
+            if($version < 0 || $version > QRSPEC_VERSION_MAX) {
+                throw new Exception('Invalid version no');
+                return -1;
+            }
+
+            $this->version = $version;
+
+            return 0;
+        }
+        
+        //----------------------------------------------------------------------
+        public function getErrorCorrectionLevel()
+        {
+            return $this->level;
+        }
+
+        //----------------------------------------------------------------------
+        public function setErrorCorrectionLevel($level)
+        {
+            if($level > QR_ECLEVEL_H) {
+                throw new Exception('Invalid ECLEVEL');
+                return -1;
+            }
+
+            $this->level = $level;
+
+            return 0;
+        }
+        
+        //----------------------------------------------------------------------
+        public function appendEntry(QRinputItem $entry)
+        {
+            $this->items[] = $entry;
+        }
+        
+        //----------------------------------------------------------------------
+        public function append($mode, $size, $data)
+        {
+            try {
+                $entry = new QRinputItem($mode, $size, $data);
+                $this->items[] = $entry;
+                return 0;
+            } catch (Exception $e) {
+                return -1;
+            }
+        }
+        
+        //----------------------------------------------------------------------
+        
+        public function insertStructuredAppendHeader($size, $index, $parity)
+        {
+            if( $size > MAX_STRUCTURED_SYMBOLS ) {
+                throw new Exception('insertStructuredAppendHeader wrong size');
+            }
+            
+            if( $index <= 0 || $index > MAX_STRUCTURED_SYMBOLS ) {
+                throw new Exception('insertStructuredAppendHeader wrong index');
+            }
+
+            $buf = array($size, $index, $parity);
+            
+            try {
+                $entry = new QRinputItem(QR_MODE_STRUCTURE, 3, buf);
+                array_unshift($this->items, $entry);
+                return 0;
+            } catch (Exception $e) {
+                return -1;
+            }
+        }
+
+        //----------------------------------------------------------------------
+        public function calcParity()
+        {
+            $parity = 0;
+            
+            foreach($this->items as $item) {
+                if($item->mode != QR_MODE_STRUCTURE) {
+                    for($i=$item->size-1; $i>=0; $i--) {
+                        $parity ^= $item->data[$i];
+                    }
+                }
+            }
+
+            return $parity;
+        }
+        
+        //----------------------------------------------------------------------
+        public static function checkModeNum($size, $data)
+        {
+            for($i=0; $i<$size; $i++) {
+                if((ord($data[$i]) < ord('0')) || (ord($data[$i]) > ord('9'))){
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+        //----------------------------------------------------------------------
+        public static function estimateBitsModeNum($size)
+        {
+            $w = (int)$size / 3;
+            $bits = $w * 10;
+            
+            switch($size - $w * 3) {
+                case 1:
+                    $bits += 4;
+                    break;
+                case 2:
+                    $bits += 7;
+                    break;
+                default:
+                    break;
+            }
+
+            return $bits;
+        }
+        
+        //----------------------------------------------------------------------
+        public static $anTable = array(
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43,
+             0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 44, -1, -1, -1, -1, -1,
+            -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+            25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+        );
+        
+        //----------------------------------------------------------------------
+        public static function lookAnTable($c)
+        {
+            return (($c > 127)?-1:self::$anTable[$c]);
+        }
+        
+        //----------------------------------------------------------------------
+        public static function checkModeAn($size, $data)
+        {
+            for($i=0; $i<$size; $i++) {
+                if (self::lookAnTable(ord($data[$i])) == -1) {
+                    return false;
+                }
+            }
+
+            return true;
+        }
+        
+        //----------------------------------------------------------------------
+        public static function estimateBitsModeAn($size)
+        {
+            $w = (int)($size / 2);
+            $bits = $w * 11;
+            
+            if($size & 1) {
+                $bits += 6;
+            }
+
+            return $bits;
+        }
+    
+        //----------------------------------------------------------------------
+        public static function estimateBitsMode8($size)
+        {
+            return $size * 8;
+        }
+        
+        //----------------------------------------------------------------------
+        public function estimateBitsModeKanji($size)
+        {
+            return (int)(($size / 2) * 13);
+        }
+        
+        //----------------------------------------------------------------------
+        public static function checkModeKanji($size, $data)
+        {
+            if($size & 1)
+                return false;
+
+            for($i=0; $i<$size; $i+=2) {
+                $val = (ord($data[$i]) << 8) | ord($data[$i+1]);
+                if( $val < 0x8140 
+                || ($val > 0x9ffc && $val < 0xe040) 
+                || $val > 0xebbf) {
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+        /***********************************************************************
+         * Validation
+         **********************************************************************/
+
+        public static function check($mode, $size, $data)
+        {
+            if($size <= 0) 
+                return false;
+
+            switch($mode) {
+                case QR_MODE_NUM:       return self::checkModeNum($size, $data);   break;
+                case QR_MODE_AN:        return self::checkModeAn($size, $data);    break;
+                case QR_MODE_KANJI:     return self::checkModeKanji($size, $data); break;
+                case QR_MODE_8:         return true; break;
+                case QR_MODE_STRUCTURE: return true; break;
+                
+                default:
+                    break;
+            }
+
+            return false;
+        }
+        
+        
+        //----------------------------------------------------------------------
+        public function estimateBitStreamSize($version)
+        {
+            $bits = 0;
+
+            foreach($this->items as $item) {
+                $bits += $item->estimateBitStreamSizeOfEntry($version);
+            }
+
+            return $bits;
+        }
+        
+        //----------------------------------------------------------------------
+        public function estimateVersion()
+        {
+            $version = 0;
+            $prev = 0;
+            do {
+                $prev = $version;
+                $bits = $this->estimateBitStreamSize($prev);
+                $version = QRspec::getMinimumVersion((int)(($bits + 7) / 8), $this->level);
+                if ($version < 0) {
+                    return -1;
+                }
+            } while ($version > $prev);
+
+            return $version;
+        }
+        
+        //----------------------------------------------------------------------
+        public static function lengthOfCode($mode, $version, $bits)
+        {
+            $payload = $bits - 4 - QRspec::lengthIndicator($mode, $version);
+            switch($mode) {
+                case QR_MODE_NUM:
+                    $chunks = (int)($payload / 10);
+                    $remain = $payload - $chunks * 10;
+                    $size = $chunks * 3;
+                    if($remain >= 7) {
+                        $size += 2;
+                    } else if($remain >= 4) {
+                        $size += 1;
+                    }
+                    break;
+                case QR_MODE_AN:
+                    $chunks = (int)($payload / 11);
+                    $remain = $payload - $chunks * 11;
+                    $size = $chunks * 2;
+                    if($remain >= 6) 
+                        $size++;
+                    break;
+                case QR_MODE_8:
+                    $size = (int)($payload / 8);
+                    break;
+                case QR_MODE_KANJI:
+                    $size = (int)(($payload / 13) * 2);
+                    break;
+                case QR_MODE_STRUCTURE:
+                    $size = (int)($payload / 8);
+                    break;
+                default:
+                    $size = 0;
+                    break;
+            }
+            
+            $maxsize = QRspec::maximumWords($mode, $version);
+            if($size < 0) $size = 0;
+            if($size > $maxsize) $size = $maxsize;
+
+            return $size;
+        }
+        
+        //----------------------------------------------------------------------
+        public function createBitStream()
+        {
+            $total = 0;
+
+            foreach($this->items as $item) {
+                $bits = $item->encodeBitStream($this->version);
+                
+                if($bits < 0) 
+                    return -1;
+                    
+                $total += $bits;
+            }
+
+            return $total;
+        }
+        
+        //----------------------------------------------------------------------
+        public function convertData()
+        {
+            $ver = $this->estimateVersion();
+            if($ver > $this->getVersion()) {
+                $this->setVersion($ver);
+            }
+
+            for(;;) {
+                $bits = $this->createBitStream();
+                
+                if($bits < 0) 
+                    return -1;
+                    
+                $ver = QRspec::getMinimumVersion((int)(($bits + 7) / 8), $this->level);
+                if($ver < 0) {
+                    throw new Exception('WRONG VERSION');
+                    return -1;
+                } else if($ver > $this->getVersion()) {
+                    $this->setVersion($ver);
+                } else {
+                    break;
+                }
+            }
+
+            return 0;
+        }
+        
+        //----------------------------------------------------------------------
+        public function appendPaddingBit(&$bstream)
+        {
+            $bits = $bstream->size();
+            $maxwords = QRspec::getDataLength($this->version, $this->level);
+            $maxbits = $maxwords * 8;
+
+            if ($maxbits == $bits) {
+                return 0;
+            }
+
+            if ($maxbits - $bits < 5) {
+                return $bstream->appendNum($maxbits - $bits, 0);
+            }
+
+            $bits += 4;
+            $words = (int)(($bits + 7) / 8);
+
+            $padding = new QRbitstream();
+            $ret = $padding->appendNum($words * 8 - $bits + 4, 0);
+            
+            if($ret < 0) 
+                return $ret;
+
+            $padlen = $maxwords - $words;
+            
+            if($padlen > 0) {
+                
+                $padbuf = array();
+                for($i=0; $i<$padlen; $i++) {
+                    $padbuf[$i] = ($i&1)?0x11:0xec;
+                }
+                
+                $ret = $padding->appendBytes($padlen, $padbuf);
+                
+                if($ret < 0)
+                    return $ret;
+                
+            }
+
+            $ret = $bstream->append($padding);
+            
+            return $ret;
+        }
+
+        //----------------------------------------------------------------------
+        public function mergeBitStream()
+        {
+            if($this->convertData() < 0) {
+                return null;
+            }
+
+            $bstream = new QRbitstream();
+            
+            foreach($this->items as $item) {
+                $ret = $bstream->append($item->bstream);
+                if($ret < 0) {
+                    return null;
+                }
+            }
+
+            return $bstream;
+        }
+
+        //----------------------------------------------------------------------
+        public function getBitStream()
+        {
+
+            $bstream = $this->mergeBitStream();
+            
+            if($bstream == null) {
+                return null;
+            }
+            
+            $ret = $this->appendPaddingBit($bstream);
+            if($ret < 0) {
+                return null;
+            }
+
+            return $bstream;
+        }
+        
+        //----------------------------------------------------------------------
+        public function getByteStream()
+        {
+            $bstream = $this->getBitStream();
+            if($bstream == null) {
+                return null;
+            }
+            
+            return $bstream->toByte();
+        }
+    }
+        
+        
+    
+
+
+
+//---- qrbitstream.php -----------------------------
+
+
+
+
+/*
+ * PHP QR Code encoder
+ *
+ * Bitstream class
+ *
+ * Based on libqrencode C library distributed under LGPL 2.1
+ * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
+ *
+ * PHP QR Code is distributed under LGPL 3
+ * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+     
+    class QRbitstream {
+    
+        public $data = array();
+        
+        //----------------------------------------------------------------------
+        public function size()
+        {
+            return count($this->data);
+        }
+        
+        //----------------------------------------------------------------------
+        public function allocate($setLength)
+        {
+            $this->data = array_fill(0, $setLength, 0);
+            return 0;
+        }
+    
+        //----------------------------------------------------------------------
+        public static function newFromNum($bits, $num)
+        {
+            $bstream = new QRbitstream();
+            $bstream->allocate($bits);
+            
+            $mask = 1 << ($bits - 1);
+            for($i=0; $i<$bits; $i++) {
+                if($num & $mask) {
+                    $bstream->data[$i] = 1;
+                } else {
+                    $bstream->data[$i] = 0;
+                }
+                $mask = $mask >> 1;
+            }
+
+            return $bstream;
+        }
+        
+        //----------------------------------------------------------------------
+        public static function newFromBytes($size, $data)
+        {
+            $bstream = new QRbitstream();
+            $bstream->allocate($size * 8);
+            $p=0;
+
+            for($i=0; $i<$size; $i++) {
+                $mask = 0x80;
+                for($j=0; $j<8; $j++) {
+                    if($data[$i] & $mask) {
+                        $bstream->data[$p] = 1;
+                    } else {
+                        $bstream->data[$p] = 0;
+                    }
+                    $p++;
+                    $mask = $mask >> 1;
+                }
+            }
+
+            return $bstream;
+        }
+        
+        //----------------------------------------------------------------------
+        public function append(QRbitstream $arg)
+        {
+            if (is_null($arg)) {
+                return -1;
+            }
+            
+            if($arg->size() == 0) {
+                return 0;
+            }
+            
+            if($this->size() == 0) {
+                $this->data = $arg->data;
+                return 0;
+            }
+            
+            $this->data = array_values(array_merge($this->data, $arg->data));
+
+            return 0;
+        }
+        
+        //----------------------------------------------------------------------
+        public function appendNum($bits, $num)
+        {
+            if ($bits == 0) 
+                return 0;
+
+            $b = QRbitstream::newFromNum($bits, $num);
+            
+            if(is_null($b))
+                return -1;
+
+            $ret = $this->append($b);
+            unset($b);
+
+            return $ret;
+        }
+
+        //----------------------------------------------------------------------
+        public function appendBytes($size, $data)
+        {
+            if ($size == 0) 
+                return 0;
+
+            $b = QRbitstream::newFromBytes($size, $data);
+            
+            if(is_null($b))
+                return -1;
+
+            $ret = $this->append($b);
+            unset($b);
+
+            return $ret;
+        }
+        
+        //----------------------------------------------------------------------
+        public function toByte()
+        {
+        
+            $size = $this->size();
+
+            if($size == 0) {
+                return array();
+            }
+            
+            $data = array_fill(0, (int)(($size + 7) / 8), 0);
+            $bytes = (int)($size / 8);
+
+            $p = 0;
+            
+            for($i=0; $i<$bytes; $i++) {
+                $v = 0;
+                for($j=0; $j<8; $j++) {
+                    $v = $v << 1;
+                    $v |= $this->data[$p];
+                    $p++;
+                }
+                $data[$i] = $v;
+            }
+            
+            if($size & 7) {
+                $v = 0;
+                for($j=0; $j<($size & 7); $j++) {
+                    $v = $v << 1;
+                    $v |= $this->data[$p];
+                    $p++;
+                }
+                $data[$bytes] = $v;
+            }
+
+            return $data;
+        }
+
+    }
+
+
+
+
+//---- qrsplit.php -----------------------------
+
+
+
+
+/*
+ * PHP QR Code encoder
+ *
+ * Input splitting classes
+ *
+ * Based on libqrencode C library distributed under LGPL 2.1
+ * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
+ *
+ * PHP QR Code is distributed under LGPL 3
+ * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
+ *
+ * The following data / specifications are taken from
+ * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
+ *  or
+ * "Automatic identification and data capture techniques -- 
+ *  QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+    class QRsplit {
+
+        public $dataStr = '';
+        public $input;
+        public $modeHint;
+
+        //----------------------------------------------------------------------
+        public function __construct($dataStr, $input, $modeHint) 
+        {
+            $this->dataStr  = $dataStr;
+            $this->input    = $input;
+            $this->modeHint = $modeHint;
+        }
+        
+        //----------------------------------------------------------------------
+        public static function isdigitat($str, $pos)
+        {    
+            if ($pos >= strlen($str))
+                return false;
+            
+            return ((ord($str[$pos]) >= ord('0'))&&(ord($str[$pos]) <= ord('9')));
+        }
+        
+        //----------------------------------------------------------------------
+        public static function isalnumat($str, $pos)
+        {
+            if ($pos >= strlen($str))
+                return false;
+                
+            return (QRinput::lookAnTable(ord($str[$pos])) >= 0);
+        }
+
+        //----------------------------------------------------------------------
+        public function identifyMode($pos)
+        {
+            if ($pos >= strlen($this->dataStr)) 
+                return QR_MODE_NUL;
+                
+            $c = $this->dataStr[$pos];
+            
+            if(self::isdigitat($this->dataStr, $pos)) {
+                return QR_MODE_NUM;
+            } else if(self::isalnumat($this->dataStr, $pos)) {
+                return QR_MODE_AN;
+            } else if($this->modeHint == QR_MODE_KANJI) {
+            
+                if ($pos+1 < strlen($this->dataStr)) 
+                {
+                    $d = $this->dataStr[$pos+1];
+                    $word = (ord($c) << 8) | ord($d);
+                    if(($word >= 0x8140 && $word <= 0x9ffc) || ($word >= 0xe040 && $word <= 0xebbf)) {
+                        return QR_MODE_KANJI;
+                    }
+                }
+            }
+
+            return QR_MODE_8;
+        } 
+        
+        //----------------------------------------------------------------------
+        public function eatNum()
+        {
+            $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
+
+            $p = 0;
+            while(self::isdigitat($this->dataStr, $p)) {
+                $p++;
+            }
+            
+            $run = $p;
+            $mode = $this->identifyMode($p);
+            
+            if($mode == QR_MODE_8) {
+                $dif = QRinput::estimateBitsModeNum($run) + 4 + $ln
+                     + QRinput::estimateBitsMode8(1)         // + 4 + l8
+                     - QRinput::estimateBitsMode8($run + 1); // - 4 - l8
+                if($dif > 0) {
+                    return $this->eat8();
+                }
+            }
+            if($mode == QR_MODE_AN) {
+                $dif = QRinput::estimateBitsModeNum($run) + 4 + $ln
+                     + QRinput::estimateBitsModeAn(1)        // + 4 + la
+                     - QRinput::estimateBitsModeAn($run + 1);// - 4 - la
+                if($dif > 0) {
+                    return $this->eatAn();
+                }
+            }
+            
+            $ret = $this->input->append(QR_MODE_NUM, $run, str_split($this->dataStr));
+            if($ret < 0)
+                return -1;
+
+            return $run;
+        }
+        
+        //----------------------------------------------------------------------
+        public function eatAn()
+        {
+            $la = QRspec::lengthIndicator(QR_MODE_AN,  $this->input->getVersion());
+            $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
+
+            $p = 0;
+            
+            while(self::isalnumat($this->dataStr, $p)) {
+                if(self::isdigitat($this->dataStr, $p)) {
+                    $q = $p;
+                    while(self::isdigitat($this->dataStr, $q)) {
+                        $q++;
+                    }
+                    
+                    $dif = QRinput::estimateBitsModeAn($p) // + 4 + la
+                         + QRinput::estimateBitsModeNum($q - $p) + 4 + $ln
+                         - QRinput::estimateBitsModeAn($q); // - 4 - la
+                         
+                    if($dif < 0) {
+                        break;
+                    } else {
+                        $p = $q;
+                    }
+                } else {
+                    $p++;
+                }
+            }
+
+            $run = $p;
+
+            if(!self::isalnumat($this->dataStr, $p)) {
+                $dif = QRinput::estimateBitsModeAn($run) + 4 + $la
+                     + QRinput::estimateBitsMode8(1) // + 4 + l8
+                      - QRinput::estimateBitsMode8($run + 1); // - 4 - l8
+                if($dif > 0) {
+                    return $this->eat8();
+                }
+            }
+
+            $ret = $this->input->append(QR_MODE_AN, $run, str_split($this->dataStr));
+            if($ret < 0)
+                return -1;
+
+            return $run;
+        }
+        
+        //----------------------------------------------------------------------
+        public function eatKanji()
+        {
+            $p = 0;
+            
+            while($this->identifyMode($p) == QR_MODE_KANJI) {
+                $p += 2;
+            }
+            
+            $ret = $this->input->append(QR_MODE_KANJI, $p, str_split($this->dataStr));
+            if($ret < 0)
+                return -1;
+
+            return $run;
+        }
+
+        //----------------------------------------------------------------------
+        public function eat8()
+        {
+            $la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion());
+            $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
+
+            $p = 1;
+            $dataStrLen = strlen($this->dataStr);
+            
+            while($p < $dataStrLen) {
+                
+                $mode = $this->identifyMode($p);
+                if($mode == QR_MODE_KANJI) {
+                    break;
+                }
+                if($mode == QR_MODE_NUM) {
+                    $q = $p;
+                    while(self::isdigitat($this->dataStr, $q)) {
+                        $q++;
+                    }
+                    $dif = QRinput::estimateBitsMode8($p) // + 4 + l8
+                         + QRinput::estimateBitsModeNum($q - $p) + 4 + $ln
+                         - QRinput::estimateBitsMode8($q); // - 4 - l8
+                    if($dif < 0) {
+                        break;
+                    } else {
+                        $p = $q;
+                    }
+                } else if($mode == QR_MODE_AN) {
+                    $q = $p;
+                    while(self::isalnumat($this->dataStr, $q)) {
+                        $q++;
+                    }
+                    $dif = QRinput::estimateBitsMode8($p)  // + 4 + l8
+                         + QRinput::estimateBitsModeAn($q - $p) + 4 + $la
+                         - QRinput::estimateBitsMode8($q); // - 4 - l8
+                    if($dif < 0) {
+                        break;
+                    } else {
+                        $p = $q;
+                    }
+                } else {
+                    $p++;
+                }
+            }
+
+            $run = $p;
+            $ret = $this->input->append(QR_MODE_8, $run, str_split($this->dataStr));
+            
+            if($ret < 0)
+                return -1;
+
+            return $run;
+        }
+
+        //----------------------------------------------------------------------
+        public function splitString()
+        {
+            while (strlen($this->dataStr) > 0)
+            {
+                if($this->dataStr == '')
+                    return 0;
+
+                $mode = $this->identifyMode(0);
+                
+                switch ($mode) {
+                    case QR_MODE_NUM: $length = $this->eatNum(); break;
+                    case QR_MODE_AN:  $length = $this->eatAn(); break;
+                    case QR_MODE_KANJI:
+                        if ($hint == QR_MODE_KANJI)
+                                $length = $this->eatKanji();
+                        else    $length = $this->eat8();
+                        break;
+                    default: $length = $this->eat8(); break;
+                
+                }
+
+                if($length == 0) return 0;
+                if($length < 0)  return -1;
+                
+                $this->dataStr = substr($this->dataStr, $length);
+            }
+        }
+
+        //----------------------------------------------------------------------
+        public function toUpper()
+        {
+            $stringLen = strlen($this->dataStr);
+            $p = 0;
+            
+            while ($p<$stringLen) {
+                $mode = self::identifyMode(substr($this->dataStr, $p), $this->modeHint);
+                if($mode == QR_MODE_KANJI) {
+                    $p += 2;
+                } else {
+                    if (ord($this->dataStr[$p]) >= ord('a') && ord($this->dataStr[$p]) <= ord('z')) {
+                        $this->dataStr[$p] = chr(ord($this->dataStr[$p]) - 32);
+                    }
+                    $p++;
+                }
+            }
+
+            return $this->dataStr;
+        }
+
+        //----------------------------------------------------------------------
+        public static function splitStringToQRinput($string, QRinput $input, $modeHint, $casesensitive = true)
+        {
+            if(is_null($string) || $string == '\0' || $string == '') {
+                throw new Exception('empty string!!!');
+            }
+
+            $split = new QRsplit($string, $input, $modeHint);
+            
+            if(!$casesensitive)
+                $split->toUpper();
+                
+            return $split->splitString();
+        }
+    }
+
+
+
+//---- qrrscode.php -----------------------------
+
+
+
+
+/*
+ * PHP QR Code encoder
+ *
+ * Reed-Solomon error correction support
+ * 
+ * Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q
+ * (libfec is released under the GNU Lesser General Public License.)
+ *
+ * Based on libqrencode C library distributed under LGPL 2.1
+ * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
+ *
+ * PHP QR Code is distributed under LGPL 3
+ * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+ 
+    class QRrsItem {
+    
+        public $mm;                  // Bits per symbol 
+        public $nn;                  // Symbols per block (= (1<<mm)-1) 
+        public $alpha_to = array();  // log lookup table 
+        public $index_of = array();  // Antilog lookup table 
+        public $genpoly = array();   // Generator polynomial 
+        public $nroots;              // Number of generator roots = number of parity symbols 
+        public $fcr;                 // First consecutive root, index form 
+        public $prim;                // Primitive element, index form 
+        public $iprim;               // prim-th root of 1, index form 
+        public $pad;                 // Padding bytes in shortened block 
+        public $gfpoly;
+    
+        //----------------------------------------------------------------------
+        public function modnn($x)
+        {
+            while ($x >= $this->nn) {
+                $x -= $this->nn;
+                $x = ($x >> $this->mm) + ($x & $this->nn);
+            }
+            
+            return $x;
+        }
+        
+        //----------------------------------------------------------------------
+        public static function init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad)
+        {
+            // Common code for intializing a Reed-Solomon control block (char or int symbols)
+            // Copyright 2004 Phil Karn, KA9Q
+            // May be used under the terms of the GNU Lesser General Public License (LGPL)
+
+            $rs = null;
+            
+            // Check parameter ranges
+            if($symsize < 0 || $symsize > 8)                     return $rs;
+            if($fcr < 0 || $fcr >= (1<<$symsize))                return $rs;
+            if($prim <= 0 || $prim >= (1<<$symsize))             return $rs;
+            if($nroots < 0 || $nroots >= (1<<$symsize))          return $rs; // Can't have more roots than symbol values!
+            if($pad < 0 || $pad >= ((1<<$symsize) -1 - $nroots)) return $rs; // Too much padding
+
+            $rs = new QRrsItem();
+            $rs->mm = $symsize;
+            $rs->nn = (1<<$symsize)-1;
+            $rs->pad = $pad;
+
+            $rs->alpha_to = array_fill(0, $rs->nn+1, 0);
+            $rs->index_of = array_fill(0, $rs->nn+1, 0);
+          
+            // PHP style macro replacement ;)
+            $NN =& $rs->nn;
+            $A0 =& $NN;
+            
+            // Generate Galois field lookup tables
+            $rs->index_of[0] = $A0; // log(zero) = -inf
+            $rs->alpha_to[$A0] = 0; // alpha**-inf = 0
+            $sr = 1;
+          
+            for($i=0; $i<$rs->nn; $i++) {
+                $rs->index_of[$sr] = $i;
+                $rs->alpha_to[$i] = $sr;
+                $sr <<= 1;
+                if($sr & (1<<$symsize)) {
+                    $sr ^= $gfpoly;
+                }
+                $sr &= $rs->nn;
+            }
+            
+            if($sr != 1){
+                // field generator polynomial is not primitive!
+                $rs = NULL;
+                return $rs;
+            }
+
+            /* Form RS code generator polynomial from its roots */
+            $rs->genpoly = array_fill(0, $nroots+1, 0);
+        
+            $rs->fcr = $fcr;
+            $rs->prim = $prim;
+            $rs->nroots = $nroots;
+            $rs->gfpoly = $gfpoly;
+
+            /* Find prim-th root of 1, used in decoding */
+            for($iprim=1;($iprim % $prim) != 0;$iprim += $rs->nn)
+            ; // intentional empty-body loop!
+            
+            $rs->iprim = (int)($iprim / $prim);
+            $rs->genpoly[0] = 1;
+            
+            for ($i = 0,$root=$fcr*$prim; $i < $nroots; $i++, $root += $prim) {
+                $rs->genpoly[$i+1] = 1;
+
+                // Multiply rs->genpoly[] by  @**(root + x)
+                for ($j = $i; $j > 0; $j--) {
+                    if ($rs->genpoly[$j] != 0) {
+                        $rs->genpoly[$j] = $rs->genpoly[$j-1] ^ $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[$j]] + $root)];
+                    } else {
+                        $rs->genpoly[$j] = $rs->genpoly[$j-1];
+                    }
+                }
+                // rs->genpoly[0] can never be zero
+                $rs->genpoly[0] = $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[0]] + $root)];
+            }
+            
+            // convert rs->genpoly[] to index form for quicker encoding
+            for ($i = 0; $i <= $nroots; $i++)
+                $rs->genpoly[$i] = $rs->index_of[$rs->genpoly[$i]];
+
+            return $rs;
+        }
+        
+        //----------------------------------------------------------------------
+        public function encode_rs_char($data, &$parity)
+        {
+            $MM       =& $this->mm;
+            $NN       =& $this->nn;
+            $ALPHA_TO =& $this->alpha_to;
+            $INDEX_OF =& $this->index_of;
+            $GENPOLY  =& $this->genpoly;
+            $NROOTS   =& $this->nroots;
+            $FCR      =& $this->fcr;
+            $PRIM     =& $this->prim;
+            $IPRIM    =& $this->iprim;
+            $PAD      =& $this->pad;
+            $A0       =& $NN;
+
+            $parity = array_fill(0, $NROOTS, 0);
+
+            for($i=0; $i< ($NN-$NROOTS-$PAD); $i++) {
+                
+                $feedback = $INDEX_OF[$data[$i] ^ $parity[0]];
+                if($feedback != $A0) {      
+                    // feedback term is non-zero
+            
+                    // This line is unnecessary when GENPOLY[NROOTS] is unity, as it must
+                    // always be for the polynomials constructed by init_rs()
+                    $feedback = $this->modnn($NN - $GENPOLY[$NROOTS] + $feedback);
+            
+                    for($j=1;$j<$NROOTS;$j++) {
+                        $parity[$j] ^= $ALPHA_TO[$this->modnn($feedback + $GENPOLY[$NROOTS-$j])];
+                    }
+                }
+                
+                // Shift 
+                array_shift($parity);
+                if($feedback != $A0) {
+                    array_push($parity, $ALPHA_TO[$this->modnn($feedback + $GENPOLY[0])]);
+                } else {
+                    array_push($parity, 0);
+                }
+            }
+        }
+    }
+    
+    //##########################################################################
+    
+    class QRrs {
+    
+        public static $items = array();
+        
+        //----------------------------------------------------------------------
+        public static function init_rs($symsize, $gfpoly, $fcr, $prim, $nroots, $pad)
+        {
+            foreach(self::$items as $rs) {
+                if($rs->pad != $pad)       continue;
+                if($rs->nroots != $nroots) continue;
+                if($rs->mm != $symsize)    continue;
+                if($rs->gfpoly != $gfpoly) continue;
+                if($rs->fcr != $fcr)       continue;
+                if($rs->prim != $prim)     continue;
+
+                return $rs;
+            }
+
+            $rs = QRrsItem::init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad);
+            array_unshift(self::$items, $rs);
+
+            return $rs;
+        }
+    }
+
+
+
+//---- qrmask.php -----------------------------
+
+
+
+
+/*
+ * PHP QR Code encoder
+ *
+ * Masking
+ *
+ * Based on libqrencode C library distributed under LGPL 2.1
+ * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
+ *
+ * PHP QR Code is distributed under LGPL 3
+ * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+ 
+	define('N1', 3);
+	define('N2', 3);
+	define('N3', 40);
+	define('N4', 10);
+
+	class QRmask {
+	
+		public $runLength = array();
+		
+		//----------------------------------------------------------------------
+		public function __construct() 
+        {
+            $this->runLength = array_fill(0, QRSPEC_WIDTH_MAX + 1, 0);
+        }
+        
+        //----------------------------------------------------------------------
+        public function writeFormatInformation($width, &$frame, $mask, $level)
+        {
+            $blacks = 0;
+            $format =  QRspec::getFormatInfo($mask, $level);
+
+            for($i=0; $i<8; $i++) {
+                if($format & 1) {
+                    $blacks += 2;
+                    $v = 0x85;
+                } else {
+                    $v = 0x84;
+                }
+                
+                $frame[8][$width - 1 - $i] = chr($v);
+                if($i < 6) {
+                    $frame[$i][8] = chr($v);
+                } else {
+                    $frame[$i + 1][8] = chr($v);
+                }
+                $format = $format >> 1;
+            }
+            
+            for($i=0; $i<7; $i++) {
+                if($format & 1) {
+                    $blacks += 2;
+                    $v = 0x85;
+                } else {
+                    $v = 0x84;
+                }
+                
+                $frame[$width - 7 + $i][8] = chr($v);
+                if($i == 0) {
+                    $frame[8][7] = chr($v);
+                } else {
+                    $frame[8][6 - $i] = chr($v);
+                }
+                
+                $format = $format >> 1;
+            }
+
+            return $blacks;
+        }
+        
+        //----------------------------------------------------------------------
+        public function mask0($x, $y) { return ($x+$y)&1;                       }
+        public function mask1($x, $y) { return ($y&1);                          }
+        public function mask2($x, $y) { return ($x%3);                          }
+        public function mask3($x, $y) { return ($x+$y)%3;                       }
+        public function mask4($x, $y) { return (((int)($y/2))+((int)($x/3)))&1; }
+        public function mask5($x, $y) { return (($x*$y)&1)+($x*$y)%3;           }
+        public function mask6($x, $y) { return ((($x*$y)&1)+($x*$y)%3)&1;       }
+        public function mask7($x, $y) { return ((($x*$y)%3)+(($x+$y)&1))&1;     }
+        
+        //----------------------------------------------------------------------
+        private function generateMaskNo($maskNo, $width, $frame)
+        {
+            $bitMask = array_fill(0, $width, array_fill(0, $width, 0));
+            
+            for($y=0; $y<$width; $y++) {
+                for($x=0; $x<$width; $x++) {
+                    if(ord($frame[$y][$x]) & 0x80) {
+                        $bitMask[$y][$x] = 0;
+                    } else {
+                        $maskFunc = call_user_func(array($this, 'mask'.$maskNo), $x, $y);
+                        $bitMask[$y][$x] = ($maskFunc == 0)?1:0;
+                    }
+                    
+                }
+            }
+            
+            return $bitMask;
+        }
+        
+        //----------------------------------------------------------------------
+        public static function serial($bitFrame)
+        {
+            $codeArr = array();
+            
+            foreach ($bitFrame as $line)
+                $codeArr[] = join('', $line);
+                
+            return gzcompress(join("\n", $codeArr), 9);
+        }
+        
+        //----------------------------------------------------------------------
+        public static function unserial($code)
+        {
+            $codeArr = array();
+            
+            $codeLines = explode("\n", gzuncompress($code));
+            foreach ($codeLines as $line)
+                $codeArr[] = str_split($line);
+            
+            return $codeArr;
+        }
+        
+        //----------------------------------------------------------------------
+        public function makeMaskNo($maskNo, $width, $s, &$d, $maskGenOnly = false) 
+        {
+            $b = 0;
+            $bitMask = array();
+            
+            $fileName = QR_CACHE_DIR.'mask_'.$maskNo.DIRECTORY_SEPARATOR.'mask_'.$width.'_'.$maskNo.'.dat';
+
+            if (QR_CACHEABLE) {
+                if (file_exists($fileName)) {
+                    $bitMask = self::unserial(file_get_contents($fileName));
+                } else {
+                    $bitMask = $this->generateMaskNo($maskNo, $width, $s, $d);
+                    if (!file_exists(QR_CACHE_DIR.'mask_'.$maskNo))
+                        mkdir(QR_CACHE_DIR.'mask_'.$maskNo);
+                    file_put_contents($fileName, self::serial($bitMask));
+                }
+            } else {
+                $bitMask = $this->generateMaskNo($maskNo, $width, $s, $d);
+            }
+
+            if ($maskGenOnly)
+                return;
+                
+            $d = $s;
+
+            for($y=0; $y<$width; $y++) {
+                for($x=0; $x<$width; $x++) {
+                    if($bitMask[$y][$x] == 1) {
+                        $d[$y][$x] = chr(ord($s[$y][$x]) ^ (int)$bitMask[$y][$x]);
+                    }
+                    $b += (int)(ord($d[$y][$x]) & 1);
+                }
+            }
+
+            return $b;
+        }
+        
+        //----------------------------------------------------------------------
+        public function makeMask($width, $frame, $maskNo, $level)
+        {
+            $masked = array_fill(0, $width, str_repeat("\0", $width));
+            $this->makeMaskNo($maskNo, $width, $frame, $masked);
+            $this->writeFormatInformation($width, $masked, $maskNo, $level);
+       
+            return $masked;
+        }
+        
+        //----------------------------------------------------------------------
+        public function calcN1N3($length)
+        {
+            $demerit = 0;
+
+            for($i=0; $i<$length; $i++) {
+                
+                if($this->runLength[$i] >= 5) {
+                    $demerit += (N1 + ($this->runLength[$i] - 5));
+                }
+                if($i & 1) {
+                    if(($i >= 3) && ($i < ($length-2)) && ($this->runLength[$i] % 3 == 0)) {
+                        $fact = (int)($this->runLength[$i] / 3);
+                        if(($this->runLength[$i-2] == $fact) &&
+                           ($this->runLength[$i-1] == $fact) &&
+                           ($this->runLength[$i+1] == $fact) &&
+                           ($this->runLength[$i+2] == $fact)) {
+                            if(($this->runLength[$i-3] < 0) || ($this->runLength[$i-3] >= (4 * $fact))) {
+                                $demerit += N3;
+                            } else if((($i+3) >= $length) || ($this->runLength[$i+3] >= (4 * $fact))) {
+                                $demerit += N3;
+                            }
+                        }
+                    }
+                }
+            }
+            return $demerit;
+        }
+        
+        //----------------------------------------------------------------------
+        public function evaluateSymbol($width, $frame)
+        {
+            $head = 0;
+            $demerit = 0;
+
+            for($y=0; $y<$width; $y++) {
+                $head = 0;
+                $this->runLength[0] = 1;
+                
+                $frameY = $frame[$y];
+                
+                if ($y>0)
+                    $frameYM = $frame[$y-1];
+                
+                for($x=0; $x<$width; $x++) {
+                    if(($x > 0) && ($y > 0)) {
+                        $b22 = ord($frameY[$x]) & ord($frameY[$x-1]) & ord($frameYM[$x]) & ord($frameYM[$x-1]);
+                        $w22 = ord($frameY[$x]) | ord($frameY[$x-1]) | ord($frameYM[$x]) | ord($frameYM[$x-1]);
+                        
+                        if(($b22 | ($w22 ^ 1))&1) {                                                                     
+                            $demerit += N2;
+                        }
+                    }
+                    if(($x == 0) && (ord($frameY[$x]) & 1)) {
+                        $this->runLength[0] = -1;
+                        $head = 1;
+                        $this->runLength[$head] = 1;
+                    } else if($x > 0) {
+                        if((ord($frameY[$x]) ^ ord($frameY[$x-1])) & 1) {
+                            $head++;
+                            $this->runLength[$head] = 1;
+                        } else {
+                            $this->runLength[$head]++;
+                        }
+                    }
+                }
+    
+                $demerit += $this->calcN1N3($head+1);
+            }
+
+            for($x=0; $x<$width; $x++) {
+                $head = 0;
+                $this->runLength[0] = 1;
+                
+                for($y=0; $y<$width; $y++) {
+                    if($y == 0 && (ord($frame[$y][$x]) & 1)) {
+                        $this->runLength[0] = -1;
+                        $head = 1;
+                        $this->runLength[$head] = 1;
+                    } else if($y > 0) {
+                        if((ord($frame[$y][$x]) ^ ord($frame[$y-1][$x])) & 1) {
+                            $head++;
+                            $this->runLength[$head] = 1;
+                        } else {
+                            $this->runLength[$head]++;
+                        }
+                    }
+                }
+            
+                $demerit += $this->calcN1N3($head+1);
+            }
+
+            return $demerit;
+        }
+        
+        
+        //----------------------------------------------------------------------
+        public function mask($width, $frame, $level)
+        {
+            $minDemerit = PHP_INT_MAX;
+            $bestMaskNum = 0;
+            $bestMask = array();
+            
+            $checked_masks = array(0,1,2,3,4,5,6,7);
+            
+            if (QR_FIND_FROM_RANDOM !== false) {
+            
+                $howManuOut = 8-(QR_FIND_FROM_RANDOM % 9);
+                for ($i = 0; $i <  $howManuOut; $i++) {
+                    $remPos = rand (0, count($checked_masks)-1);
+                    unset($checked_masks[$remPos]);
+                    $checked_masks = array_values($checked_masks);
+                }
+            
+            }
+            
+            $bestMask = $frame;
+             
+            foreach($checked_masks as $i) {
+                $mask = array_fill(0, $width, str_repeat("\0", $width));
+
+                $demerit = 0;
+                $blacks = 0;
+                $blacks  = $this->makeMaskNo($i, $width, $frame, $mask);
+                $blacks += $this->writeFormatInformation($width, $mask, $i, $level);
+                $blacks  = (int)(100 * $blacks / ($width * $width));
+                $demerit = (int)((int)(abs($blacks - 50) / 5) * N4);
+                $demerit += $this->evaluateSymbol($width, $mask);
+                
+                if($demerit < $minDemerit) {
+                    $minDemerit = $demerit;
+                    $bestMask = $mask;
+                    $bestMaskNum = $i;
+                }
+            }
+            
+            return $bestMask;
+        }
+        
+        //----------------------------------------------------------------------
+    }
+
+
+
+
+//---- qrencode.php -----------------------------
+
+
+
+
+/*
+ * PHP QR Code encoder
+ *
+ * Main encoder classes.
+ *
+ * Based on libqrencode C library distributed under LGPL 2.1
+ * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
+ *
+ * PHP QR Code is distributed under LGPL 3
+ * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+ 
+    class QRrsblock {
+        public $dataLength;
+        public $data = array();
+        public $eccLength;
+        public $ecc = array();
+        
+        public function __construct($dl, $data, $el, &$ecc, QRrsItem $rs)
+        {
+            $rs->encode_rs_char($data, $ecc);
+        
+            $this->dataLength = $dl;
+            $this->data = $data;
+            $this->eccLength = $el;
+            $this->ecc = $ecc;
+        }
+    };
+    
+    //##########################################################################
+
+    class QRrawcode {
+        public $version;
+        public $datacode = array();
+        public $ecccode = array();
+        public $blocks;
+        public $rsblocks = array(); //of RSblock
+        public $count;
+        public $dataLength;
+        public $eccLength;
+        public $b1;
+        
+        //----------------------------------------------------------------------
+        public function __construct(QRinput $input)
+        {
+            $spec = array(0,0,0,0,0);
+            
+            $this->datacode = $input->getByteStream();
+            if(is_null($this->datacode)) {
+                throw new Exception('null imput string');
+            }
+
+            QRspec::getEccSpec($input->getVersion(), $input->getErrorCorrectionLevel(), $spec);
+
+            $this->version = $input->getVersion();
+            $this->b1 = QRspec::rsBlockNum1($spec);
+            $this->dataLength = QRspec::rsDataLength($spec);
+            $this->eccLength = QRspec::rsEccLength($spec);
+            $this->ecccode = array_fill(0, $this->eccLength, 0);
+            $this->blocks = QRspec::rsBlockNum($spec);
+            
+            $ret = $this->init($spec);
+            if($ret < 0) {
+                throw new Exception('block alloc error');
+                return null;
+            }
+
+            $this->count = 0;
+        }
+        
+        //----------------------------------------------------------------------
+        public function init(array $spec)
+        {
+            $dl = QRspec::rsDataCodes1($spec);
+            $el = QRspec::rsEccCodes1($spec);
+            $rs = QRrs::init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el);
+            
+
+            $blockNo = 0;
+            $dataPos = 0;
+            $eccPos = 0;
+            for($i=0; $i<QRspec::rsBlockNum1($spec); $i++) {
+                $ecc = array_slice($this->ecccode,$eccPos);
+                $this->rsblocks[$blockNo] = new QRrsblock($dl, array_slice($this->datacode, $dataPos), $el,  $ecc, $rs);
+                $this->ecccode = array_merge(array_slice($this->ecccode,0, $eccPos), $ecc);
+                
+                $dataPos += $dl;
+                $eccPos += $el;
+                $blockNo++;
+            }
+
+            if(QRspec::rsBlockNum2($spec) == 0)
+                return 0;
+
+            $dl = QRspec::rsDataCodes2($spec);
+            $el = QRspec::rsEccCodes2($spec);
+            $rs = QRrs::init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el);
+            
+            if($rs == NULL) return -1;
+            
+            for($i=0; $i<QRspec::rsBlockNum2($spec); $i++) {
+                $ecc = array_slice($this->ecccode,$eccPos);
+                $this->rsblocks[$blockNo] = new QRrsblock($dl, array_slice($this->datacode, $dataPos), $el, $ecc, $rs);
+                $this->ecccode = array_merge(array_slice($this->ecccode,0, $eccPos), $ecc);
+                
+                $dataPos += $dl;
+                $eccPos += $el;
+                $blockNo++;
+            }
+
+            return 0;
+        }
+        
+        //----------------------------------------------------------------------
+        public function getCode()
+        {
+            $ret;
+
+            if($this->count < $this->dataLength) {
+                $row = $this->count % $this->blocks;
+                $col = $this->count / $this->blocks;
+                if($col >= $this->rsblocks[0]->dataLength) {
+                    $row += $this->b1;
+                }
+                $ret = $this->rsblocks[$row]->data[$col];
+            } else if($this->count < $this->dataLength + $this->eccLength) {
+                $row = ($this->count - $this->dataLength) % $this->blocks;
+                $col = ($this->count - $this->dataLength) / $this->blocks;
+                $ret = $this->rsblocks[$row]->ecc[$col];
+            } else {
+                return 0;
+            }
+            $this->count++;
+            
+            return $ret;
+        }
+    }
+
+    //##########################################################################
+    
+    class QRcode {
+    
+        public $version;
+        public $width;
+        public $data; 
+        
+        //----------------------------------------------------------------------
+        public function encodeMask(QRinput $input, $mask)
+        {
+            if($input->getVersion() < 0 || $input->getVersion() > QRSPEC_VERSION_MAX) {
+                throw new Exception('wrong version');
+            }
+            if($input->getErrorCorrectionLevel() > QR_ECLEVEL_H) {
+                throw new Exception('wrong level');
+            }
+
+            $raw = new QRrawcode($input);
+            
+            QRtools::markTime('after_raw');
+            
+            $version = $raw->version;
+            $width = QRspec::getWidth($version);
+            $frame = QRspec::newFrame($version);
+            
+            $filler = new FrameFiller($width, $frame);
+            if(is_null($filler)) {
+                return NULL;
+            }
+
+            // inteleaved data and ecc codes
+            for($i=0; $i<$raw->dataLength + $raw->eccLength; $i++) {
+                $code = $raw->getCode();
+                $bit = 0x80;
+                for($j=0; $j<8; $j++) {
+                    $addr = $filler->next();
+                    $filler->setFrameAt($addr, 0x02 | (($bit & $code) != 0));
+                    $bit = $bit >> 1;
+                }
+            }
+            
+            QRtools::markTime('after_filler');
+            
+            unset($raw);
+            
+            // remainder bits
+            $j = QRspec::getRemainder($version);
+            for($i=0; $i<$j; $i++) {
+                $addr = $filler->next();
+                $filler->setFrameAt($addr, 0x02);
+            }
+            
+            $frame = $filler->frame;
+            unset($filler);
+            
+            
+            // masking
+            $maskObj = new QRmask();
+            if($mask < 0) {
+            
+                if (QR_FIND_BEST_MASK) {
+                    $masked = $maskObj->mask($width, $frame, $input->getErrorCorrectionLevel());
+                } else {
+                    $masked = $maskObj->makeMask($width, $frame, (intval(QR_DEFAULT_MASK) % 8), $input->getErrorCorrectionLevel());
+                }
+            } else {
+                $masked = $maskObj->makeMask($width, $frame, $mask, $input->getErrorCorrectionLevel());
+            }
+            
+            if($masked == NULL) {
+                return NULL;
+            }
+            
+            QRtools::markTime('after_mask');
+            
+            $this->version = $version;
+            $this->width = $width;
+            $this->data = $masked;
+            
+            return $this;
+        }
+    
+        //----------------------------------------------------------------------
+        public function encodeInput(QRinput $input)
+        {
+            return $this->encodeMask($input, -1);
+        }
+        
+        //----------------------------------------------------------------------
+        public function encodeString8bit($string, $version, $level)
+        {
+            if(string == NULL) {
+                throw new Exception('empty string!');
+                return NULL;
+            }
+
+            $input = new QRinput($version, $level);
+            if($input == NULL) return NULL;
+
+            $ret = $input->append($input, QR_MODE_8, strlen($string), str_split($string));
+            if($ret < 0) {
+                unset($input);
+                return NULL;
+            }
+            return $this->encodeInput($input);
+        }
+
+        //----------------------------------------------------------------------
+        public function encodeString($string, $version, $level, $hint, $casesensitive)
+        {
+
+            if($hint != QR_MODE_8 && $hint != QR_MODE_KANJI) {
+                throw new Exception('bad hint');
+                return NULL;
+            }
+
+            $input = new QRinput($version, $level);
+            if($input == NULL) return NULL;
+
+            $ret = QRsplit::splitStringToQRinput($string, $input, $hint, $casesensitive);
+            if($ret < 0) {
+                return NULL;
+            }
+
+            return $this->encodeInput($input);
+        }
+        
+        //----------------------------------------------------------------------
+        public static function png($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4, $saveandprint=false) 
+        {
+            $enc = QRencode::factory($level, $size, $margin);
+            return $enc->encodePNG($text, $outfile, $saveandprint=false);
+        }
+
+        //----------------------------------------------------------------------
+        public static function text($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4) 
+        {
+            $enc = QRencode::factory($level, $size, $margin);
+            return $enc->encode($text, $outfile);
+        }
+
+        //----------------------------------------------------------------------
+        public static function raw($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4) 
+        {
+            $enc = QRencode::factory($level, $size, $margin);
+            return $enc->encodeRAW($text, $outfile);
+        }
+    }
+    
+    //##########################################################################
+    
+    class FrameFiller {
+    
+        public $width;
+        public $frame;
+        public $x;
+        public $y;
+        public $dir;
+        public $bit;
+        
+        //----------------------------------------------------------------------
+        public function __construct($width, &$frame)
+        {
+            $this->width = $width;
+            $this->frame = $frame;
+            $this->x = $width - 1;
+            $this->y = $width - 1;
+            $this->dir = -1;
+            $this->bit = -1;
+        }
+        
+        //----------------------------------------------------------------------
+        public function setFrameAt($at, $val)
+        {
+            $this->frame[$at['y']][$at['x']] = chr($val);
+        }
+        
+        //----------------------------------------------------------------------
+        public function getFrameAt($at)
+        {
+            return ord($this->frame[$at['y']][$at['x']]);
+        }
+        
+        //----------------------------------------------------------------------
+        public function next()
+        {
+            do {
+            
+                if($this->bit == -1) {
+                    $this->bit = 0;
+                    return array('x'=>$this->x, 'y'=>$this->y);
+                }
+
+                $x = $this->x;
+                $y = $this->y;
+                $w = $this->width;
+
+                if($this->bit == 0) {
+                    $x--;
+                    $this->bit++;
+                } else {
+                    $x++;
+                    $y += $this->dir;
+                    $this->bit--;
+                }
+
+                if($this->dir < 0) {
+                    if($y < 0) {
+                        $y = 0;
+                        $x -= 2;
+                        $this->dir = 1;
+                        if($x == 6) {
+                            $x--;
+                            $y = 9;
+                        }
+                    }
+                } else {
+                    if($y == $w) {
+                        $y = $w - 1;
+                        $x -= 2;
+                        $this->dir = -1;
+                        if($x == 6) {
+                            $x--;
+                            $y -= 8;
+                        }
+                    }
+                }
+                if($x < 0 || $y < 0) return null;
+
+                $this->x = $x;
+                $this->y = $y;
+
+            } while(ord($this->frame[$y][$x]) & 0x80);
+                        
+            return array('x'=>$x, 'y'=>$y);
+        }
+        
+    } ;
+    
+    //##########################################################################    
+    
+    class QRencode {
+    
+        public $casesensitive = true;
+        public $eightbit = false;
+        
+        public $version = 0;
+        public $size = 3;
+        public $margin = 4;
+        
+        public $structured = 0; // not supported yet
+        
+        public $level = QR_ECLEVEL_L;
+        public $hint = QR_MODE_8;
+        
+        //----------------------------------------------------------------------
+        public static function factory($level = QR_ECLEVEL_L, $size = 3, $margin = 4)
+        {
+            $enc = new QRencode();
+            $enc->size = $size;
+            $enc->margin = $margin;
+            
+            switch ($level.'') {
+                case '0':
+                case '1':
+                case '2':
+                case '3':
+                        $enc->level = $level;
+                    break;
+                case 'l':
+                case 'L':
+                        $enc->level = QR_ECLEVEL_L;
+                    break;
+                case 'm':
+                case 'M':
+                        $enc->level = QR_ECLEVEL_M;
+                    break;
+                case 'q':
+                case 'Q':
+                        $enc->level = QR_ECLEVEL_Q;
+                    break;
+                case 'h':
+                case 'H':
+                        $enc->level = QR_ECLEVEL_H;
+                    break;
+            }
+            
+            return $enc;
+        }
+        
+        //----------------------------------------------------------------------
+        public function encodeRAW($intext, $outfile = false) 
+        {
+            $code = new QRcode();
+
+            if($this->eightbit) {
+                $code->encodeString8bit($intext, $this->version, $this->level);
+            } else {
+                $code->encodeString($intext, $this->version, $this->level, $this->hint, $this->casesensitive);
+            }
+            
+            return $code->data;
+        }
+
+        //----------------------------------------------------------------------
+        public function encode($intext, $outfile = false) 
+        {
+            $code = new QRcode();
+
+            if($this->eightbit) {
+                $code->encodeString8bit($intext, $this->version, $this->level);
+            } else {
+                $code->encodeString($intext, $this->version, $this->level, $this->hint, $this->casesensitive);
+            }
+            
+            QRtools::markTime('after_encode');
+            
+            if ($outfile!== false) {
+                file_put_contents($outfile, join("\n", QRtools::binarize($code->data)));
+            } else {
+                return QRtools::binarize($code->data);
+            }
+        }
+        
+        //----------------------------------------------------------------------
+        public function encodePNG($intext, $outfile = false,$saveandprint=false) 
+        {
+            try {
+            
+                ob_start();
+                $tab = $this->encode($intext);
+                $err = ob_get_contents();
+                ob_end_clean();
+                
+                if ($err != '')
+                    QRtools::log($outfile, $err);
+                
+                $maxSize = (int)(QR_PNG_MAXIMUM_SIZE / (count($tab)+2*$this->margin));
+                
+                QRimage::png($tab, $outfile, min(max(1, $this->size), $maxSize), $this->margin,$saveandprint);
+            
+            } catch (Exception $e) {
+            
+                QRtools::log($outfile, $e->getMessage());
+            
+            }
+        }
+    }
+
+

+ 5 - 0
extend/wxpay/example/qrcode.php

@@ -0,0 +1,5 @@
+<?php
+error_reporting(E_ERROR);
+require_once 'phpqrcode/phpqrcode.php';
+$url = urldecode($_GET["data"]);
+QRcode::png($url);

+ 71 - 0
extend/wxpay/example/refund.php

@@ -0,0 +1,71 @@
+<html>
+<head>
+    <meta http-equiv="content-type" content="text/html;charset=utf-8"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1" /> 
+    <title>微信支付样例-退款</title>
+</head>
+<?php
+ini_set('date.timezone','Asia/Shanghai');
+error_reporting(E_ERROR);
+require_once "../lib/WxPay.Api.php";
+require_once 'log.php';
+
+//初始化日志
+$logHandler= new CLogFileHandler("../logs/".date('Y-m-d').'.log');
+$log = Log::Init($logHandler, 15);
+
+function printf_info($data)
+{
+    foreach($data as $key=>$value){
+        echo "<font color='#f00;'>$key</font> : $value <br/>";
+    }
+}
+
+if(isset($_REQUEST["transaction_id"]) && $_REQUEST["transaction_id"] != ""){
+	$transaction_id = $_REQUEST["transaction_id"];
+	$total_fee = $_REQUEST["total_fee"];
+	$refund_fee = $_REQUEST["refund_fee"];
+	$input = new WxPayRefund();
+	$input->SetTransaction_id($transaction_id);
+	$input->SetTotal_fee($total_fee);
+	$input->SetRefund_fee($refund_fee);
+    $input->SetOut_refund_no(WxPayConfig::MCHID.date("YmdHis"));
+    $input->SetOp_user_id(WxPayConfig::MCHID);
+	printf_info(WxPayApi::refund($input));
+	exit();
+}
+
+//$_REQUEST["out_trade_no"]= "122531270220150304194108";
+///$_REQUEST["total_fee"]= "1";
+//$_REQUEST["refund_fee"] = "1";
+if(isset($_REQUEST["out_trade_no"]) && $_REQUEST["out_trade_no"] != ""){
+	$out_trade_no = $_REQUEST["out_trade_no"];
+	$total_fee = $_REQUEST["total_fee"];
+	$refund_fee = $_REQUEST["refund_fee"];
+	$input = new WxPayRefund();
+	$input->SetOut_trade_no($out_trade_no);
+	$input->SetTotal_fee($total_fee);
+	$input->SetRefund_fee($refund_fee);
+    $input->SetOut_refund_no(WxPayConfig::MCHID.date("YmdHis"));
+    $input->SetOp_user_id(WxPayConfig::MCHID);
+	printf_info(WxPayApi::refund($input));
+	exit();
+}
+?>
+<body>  
+	<form action="#" method="post">
+        <div style="margin-left:2%;color:#f00">微信订单号和商户订单号选少填一个,微信订单号优先:</div><br/>
+        <div style="margin-left:2%;">微信订单号:</div><br/>
+        <input type="text" style="width:96%;height:35px;margin-left:2%;" name="transaction_id" /><br /><br />
+        <div style="margin-left:2%;">商户订单号:</div><br/>
+        <input type="text" style="width:96%;height:35px;margin-left:2%;" name="out_trade_no" /><br /><br />
+        <div style="margin-left:2%;">订单总金额(分):</div><br/>
+        <input type="text" style="width:96%;height:35px;margin-left:2%;" name="total_fee" /><br /><br />
+        <div style="margin-left:2%;">退款金额(分):</div><br/>
+        <input type="text" style="width:96%;height:35px;margin-left:2%;" name="refund_fee" /><br /><br />
+		<div align="center">
+			<input type="submit" value="提交退款" style="width:210px; height:50px; border-radius: 15px;background-color:#FE6714; border:0px #FE6714 solid; cursor: pointer;  color:white;  font-size:16px;" type="button" onclick="callpay()" />
+		</div>
+	</form>
+</body>
+</html>

+ 73 - 0
extend/wxpay/example/refundquery.php

@@ -0,0 +1,73 @@
+<html>
+<head>
+    <meta http-equiv="content-type" content="text/html;charset=utf-8"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1" /> 
+    <title>微信支付样例-查退款单</title>
+</head>
+<?php
+ini_set('date.timezone','Asia/Shanghai');
+error_reporting(E_ERROR);
+require_once "../lib/WxPay.Api.php";
+require_once 'log.php';
+
+//初始化日志
+$logHandler= new CLogFileHandler("../logs/".date('Y-m-d').'.log');
+$log = Log::Init($logHandler, 15);
+
+
+function printf_info($data)
+{
+    foreach($data as $key=>$value){
+        echo "<font color='#f00;'>$key</font> : $value <br/>";
+    }
+}
+
+if(isset($_REQUEST["transaction_id"]) && $_REQUEST["transaction_id"] != ""){
+	$transaction_id = $_REQUEST["transaction_id"];
+	$input = new WxPayRefundQuery();
+	$input->SetTransaction_id($transaction_id);
+	printf_info(WxPayApi::refundQuery($input));
+}
+
+if(isset($_REQUEST["out_trade_no"]) && $_REQUEST["out_trade_no"] != ""){
+	$out_trade_no = $_REQUEST["out_trade_no"];
+	$input = new WxPayRefundQuery();
+	$input->SetOut_trade_no($out_trade_no);
+	printf_info(WxPayApi::refundQuery($input));
+	exit();
+}
+
+if(isset($_REQUEST["out_refund_no"]) && $_REQUEST["out_refund_no"] != ""){
+	$out_refund_no = $_REQUEST["out_refund_no"];
+	$input = new WxPayRefundQuery();
+	$input->SetOut_refund_no($out_refund_no);
+	printf_info(WxPayApi::refundQuery($input));
+	exit();
+}
+
+if(isset($_REQUEST["refund_id"]) && $_REQUEST["refund_id"] != ""){
+	$refund_id = $_REQUEST["refund_id"];
+	$input = new WxPayRefundQuery();
+	$input->SetRefund_id($refund_id);
+	printf_info(WxPayApi::refundQuery($input));
+	exit();
+}
+	
+?>
+<body>  
+	<form action="#" method="post">
+        <div style="margin-left:2%;color:#f00">微信订单号、商户订单号、微信订单号、微信退款单号选填至少一个,微信退款单号优先:</div><br/>
+        <div style="margin-left:2%;">微信订单号:</div><br/>
+        <input type="text" style="width:96%;height:35px;margin-left:2%;" name="transaction_id" /><br /><br />
+        <div style="margin-left:2%;">商户订单号:</div><br/>
+        <input type="text" style="width:96%;height:35px;margin-left:2%;" name="out_trade_no" /><br /><br />
+        <div style="margin-left:2%;">商户退款单号:</div><br/>
+        <input type="text" style="width:96%;height:35px;margin-left:2%;" name="out_refund_no" /><br /><br />
+        <div style="margin-left:2%;">微信退款单号:</div><br/>
+        <input type="text" style="width:96%;height:35px;margin-left:2%;" name="refund_id" /><br /><br />
+		<div align="center">
+			<input type="submit" value="查询" style="width:210px; height:50px; border-radius: 15px;background-color:#FE6714; border:0px #FE6714 solid; cursor: pointer;  color:white;  font-size:16px;" type="button" onclick="callpay()" />
+		</div>
+	</form>
+</body>
+</html>

BIN
extend/wxpay/image/bk.png


BIN
extend/wxpay/image/image001.jpg


BIN
extend/wxpay/image/image002.png


+ 581 - 0
extend/wxpay/lib/WxPay.Api.php

@@ -0,0 +1,581 @@
+<?php
+require_once "WxPay.Exception.php";
+require_once "WxPay.Config.php";
+require_once "WxPay.Data.php";
+
+/**
+ * 
+ * 接口访问类,包含所有微信支付API列表的封装,类中方法为static方法,
+ * 每个接口有默认超时时间(除提交被扫支付为10s,上报超时时间为1s外,其他均为6s)
+ * @author widyhu
+ *
+ */
+class WxPayApi
+{
+	/**
+	 * 
+	 * 统一下单,WxPayUnifiedOrder中out_trade_no、body、total_fee、trade_type必填
+	 * appid、mchid、spbill_create_ip、nonce_str不需要填入
+	 * @param WxPayUnifiedOrder $inputObj
+	 * @param int $timeOut
+	 * @throws WxPayException
+	 * @return 成功时返回,其他抛异常
+	 */
+	public static function unifiedOrder($inputObj, $timeOut = 6)
+	{
+		$url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
+		//检测必填参数
+		if(!$inputObj->IsOut_trade_noSet()) {
+			throw new WxPayException("缺少统一支付接口必填参数out_trade_no!");
+		}else if(!$inputObj->IsBodySet()){
+			throw new WxPayException("缺少统一支付接口必填参数body!");
+		}else if(!$inputObj->IsTotal_feeSet()) {
+			throw new WxPayException("缺少统一支付接口必填参数total_fee!");
+		}else if(!$inputObj->IsTrade_typeSet()) {
+			throw new WxPayException("缺少统一支付接口必填参数trade_type!");
+		}
+		
+		//关联参数
+		if($inputObj->GetTrade_type() == "JSAPI" && !$inputObj->IsOpenidSet()){
+			throw new WxPayException("统一支付接口中,缺少必填参数openid!trade_type为JSAPI时,openid为必填参数!");
+		}
+		if($inputObj->GetTrade_type() == "NATIVE" && !$inputObj->IsProduct_idSet()){
+			throw new WxPayException("统一支付接口中,缺少必填参数product_id!trade_type为JSAPI时,product_id为必填参数!");
+		}
+		
+		//异步通知url未设置,则使用配置文件中的url
+		if(!$inputObj->IsNotify_urlSet()){
+			$inputObj->SetNotify_url(WxPayConfig::NOTIFY_URL);//异步通知url
+		}
+		
+		$inputObj->SetAppid(WxPayConfig::APPID);//公众账号ID
+		$inputObj->SetMch_id(WxPayConfig::MCHID);//商户号
+		$inputObj->SetSpbill_create_ip($_SERVER['REMOTE_ADDR']);//终端ip	  
+		//$inputObj->SetSpbill_create_ip("1.1.1.1");  	    
+		$inputObj->SetNonce_str(self::getNonceStr());//随机字符串
+		
+		//签名
+		$inputObj->SetSign();
+		$xml = $inputObj->ToXml();
+		
+		$startTimeStamp = self::getMillisecond();//请求开始时间
+		$response = self::postXmlCurl($xml, $url, false, $timeOut);
+		$result = WxPayResults::Init($response);
+		self::reportCostTime($url, $startTimeStamp, $result);//上报请求花费时间
+		
+		return $result;
+	}
+	
+	/**
+	 * 
+	 * 查询订单,WxPayOrderQuery中out_trade_no、transaction_id至少填一个
+	 * appid、mchid、spbill_create_ip、nonce_str不需要填入
+	 * @param WxPayOrderQuery $inputObj
+	 * @param int $timeOut
+	 * @throws WxPayException
+	 * @return 成功时返回,其他抛异常
+	 */
+	public static function orderQuery($inputObj, $timeOut = 6)
+	{
+		$url = "https://api.mch.weixin.qq.com/pay/orderquery";
+		//检测必填参数
+		if(!$inputObj->IsOut_trade_noSet() && !$inputObj->IsTransaction_idSet()) {
+			throw new WxPayException("订单查询接口中,out_trade_no、transaction_id至少填一个!");
+		}
+		$inputObj->SetAppid(WxPayConfig::APPID);//公众账号ID
+		$inputObj->SetMch_id(WxPayConfig::MCHID);//商户号
+		$inputObj->SetNonce_str(self::getNonceStr());//随机字符串
+		
+		$inputObj->SetSign();//签名
+		$xml = $inputObj->ToXml();
+		
+		$startTimeStamp = self::getMillisecond();//请求开始时间
+		$response = self::postXmlCurl($xml, $url, false, $timeOut);
+		$result = WxPayResults::Init($response);
+		self::reportCostTime($url, $startTimeStamp, $result);//上报请求花费时间
+		
+		return $result;
+	}
+	
+	/**
+	 * 
+	 * 关闭订单,WxPayCloseOrder中out_trade_no必填
+	 * appid、mchid、spbill_create_ip、nonce_str不需要填入
+	 * @param WxPayCloseOrder $inputObj
+	 * @param int $timeOut
+	 * @throws WxPayException
+	 * @return 成功时返回,其他抛异常
+	 */
+	public static function closeOrder($inputObj, $timeOut = 6)
+	{
+		$url = "https://api.mch.weixin.qq.com/pay/closeorder";
+		//检测必填参数
+		if(!$inputObj->IsOut_trade_noSet()) {
+			throw new WxPayException("订单查询接口中,out_trade_no必填!");
+		}
+		$inputObj->SetAppid(WxPayConfig::APPID);//公众账号ID
+		$inputObj->SetMch_id(WxPayConfig::MCHID);//商户号
+		$inputObj->SetNonce_str(self::getNonceStr());//随机字符串
+		
+		$inputObj->SetSign();//签名
+		$xml = $inputObj->ToXml();
+		
+		$startTimeStamp = self::getMillisecond();//请求开始时间
+		$response = self::postXmlCurl($xml, $url, false, $timeOut);
+		$result = WxPayResults::Init($response);
+		self::reportCostTime($url, $startTimeStamp, $result);//上报请求花费时间
+		
+		return $result;
+	}
+
+	/**
+	 * 
+	 * 申请退款,WxPayRefund中out_trade_no、transaction_id至少填一个且
+	 * out_refund_no、total_fee、refund_fee、op_user_id为必填参数
+	 * appid、mchid、spbill_create_ip、nonce_str不需要填入
+	 * @param WxPayRefund $inputObj
+	 * @param int $timeOut
+	 * @throws WxPayException
+	 * @return 成功时返回,其他抛异常
+	 */
+	public static function refund($inputObj, $timeOut = 6)
+	{
+		$url = "https://api.mch.weixin.qq.com/secapi/pay/refund";
+		//检测必填参数
+		if(!$inputObj->IsOut_trade_noSet() && !$inputObj->IsTransaction_idSet()) {
+			throw new WxPayException("退款申请接口中,out_trade_no、transaction_id至少填一个!");
+		}else if(!$inputObj->IsOut_refund_noSet()){
+			throw new WxPayException("退款申请接口中,缺少必填参数out_refund_no!");
+		}else if(!$inputObj->IsTotal_feeSet()){
+			throw new WxPayException("退款申请接口中,缺少必填参数total_fee!");
+		}else if(!$inputObj->IsRefund_feeSet()){
+			throw new WxPayException("退款申请接口中,缺少必填参数refund_fee!");
+		}else if(!$inputObj->IsOp_user_idSet()){
+			throw new WxPayException("退款申请接口中,缺少必填参数op_user_id!");
+		}
+		$inputObj->SetAppid(WxPayConfig::APPID);//公众账号ID
+		$inputObj->SetMch_id(WxPayConfig::MCHID);//商户号
+		$inputObj->SetNonce_str(self::getNonceStr());//随机字符串
+		
+		$inputObj->SetSign();//签名
+		$xml = $inputObj->ToXml();
+		$startTimeStamp = self::getMillisecond();//请求开始时间
+		$response = self::postXmlCurl($xml, $url, true, $timeOut);
+		$result = WxPayResults::Init($response);
+		self::reportCostTime($url, $startTimeStamp, $result);//上报请求花费时间
+		
+		return $result;
+	}
+	
+	/**
+	 * 
+	 * 查询退款
+	 * 提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,
+	 * 用零钱支付的退款20分钟内到账,银行卡支付的退款3个工作日后重新查询退款状态。
+	 * WxPayRefundQuery中out_refund_no、out_trade_no、transaction_id、refund_id四个参数必填一个
+	 * appid、mchid、spbill_create_ip、nonce_str不需要填入
+	 * @param WxPayRefundQuery $inputObj
+	 * @param int $timeOut
+	 * @throws WxPayException
+	 * @return 成功时返回,其他抛异常
+	 */
+	public static function refundQuery($inputObj, $timeOut = 6)
+	{
+		$url = "https://api.mch.weixin.qq.com/pay/refundquery";
+		//检测必填参数
+		if(!$inputObj->IsOut_refund_noSet() &&
+			!$inputObj->IsOut_trade_noSet() &&
+			!$inputObj->IsTransaction_idSet() &&
+			!$inputObj->IsRefund_idSet()) {
+			throw new WxPayException("退款查询接口中,out_refund_no、out_trade_no、transaction_id、refund_id四个参数必填一个!");
+		}
+		$inputObj->SetAppid(WxPayConfig::APPID);//公众账号ID
+		$inputObj->SetMch_id(WxPayConfig::MCHID);//商户号
+		$inputObj->SetNonce_str(self::getNonceStr());//随机字符串
+		
+		$inputObj->SetSign();//签名
+		$xml = $inputObj->ToXml();
+		
+		$startTimeStamp = self::getMillisecond();//请求开始时间
+		$response = self::postXmlCurl($xml, $url, false, $timeOut);
+		$result = WxPayResults::Init($response);
+		self::reportCostTime($url, $startTimeStamp, $result);//上报请求花费时间
+		
+		return $result;
+	}
+	
+	/**
+	 * 下载对账单,WxPayDownloadBill中bill_date为必填参数
+	 * appid、mchid、spbill_create_ip、nonce_str不需要填入
+	 * @param WxPayDownloadBill $inputObj
+	 * @param int $timeOut
+	 * @throws WxPayException
+	 * @return 成功时返回,其他抛异常
+	 */
+	public static function downloadBill($inputObj, $timeOut = 6)
+	{
+		$url = "https://api.mch.weixin.qq.com/pay/downloadbill";
+		//检测必填参数
+		if(!$inputObj->IsBill_dateSet()) {
+			throw new WxPayException("对账单接口中,缺少必填参数bill_date!");
+		}
+		$inputObj->SetAppid(WxPayConfig::APPID);//公众账号ID
+		$inputObj->SetMch_id(WxPayConfig::MCHID);//商户号
+		$inputObj->SetNonce_str(self::getNonceStr());//随机字符串
+		
+		$inputObj->SetSign();//签名
+		$xml = $inputObj->ToXml();
+		
+		$response = self::postXmlCurl($xml, $url, false, $timeOut);
+		if(substr($response, 0 , 5) == "<xml>"){
+			return "";
+		}
+		return $response;
+	}
+	
+	/**
+	 * 提交被扫支付API
+	 * 收银员使用扫码设备读取微信用户刷卡授权码以后,二维码或条码信息传送至商户收银台,
+	 * 由商户收银台或者商户后台调用该接口发起支付。
+	 * WxPayWxPayMicroPay中body、out_trade_no、total_fee、auth_code参数必填
+	 * appid、mchid、spbill_create_ip、nonce_str不需要填入
+	 * @param WxPayWxPayMicroPay $inputObj
+	 * @param int $timeOut
+	 */
+	public static function micropay($inputObj, $timeOut = 10)
+	{
+		$url = "https://api.mch.weixin.qq.com/pay/micropay";
+		//检测必填参数
+		if(!$inputObj->IsBodySet()) {
+			throw new WxPayException("提交被扫支付API接口中,缺少必填参数body!");
+		} else if(!$inputObj->IsOut_trade_noSet()) {
+			throw new WxPayException("提交被扫支付API接口中,缺少必填参数out_trade_no!");
+		} else if(!$inputObj->IsTotal_feeSet()) {
+			throw new WxPayException("提交被扫支付API接口中,缺少必填参数total_fee!");
+		} else if(!$inputObj->IsAuth_codeSet()) {
+			throw new WxPayException("提交被扫支付API接口中,缺少必填参数auth_code!");
+		}
+		
+		$inputObj->SetSpbill_create_ip($_SERVER['REMOTE_ADDR']);//终端ip
+		$inputObj->SetAppid(WxPayConfig::APPID);//公众账号ID
+		$inputObj->SetMch_id(WxPayConfig::MCHID);//商户号
+		$inputObj->SetNonce_str(self::getNonceStr());//随机字符串
+		
+		$inputObj->SetSign();//签名
+		$xml = $inputObj->ToXml();
+		
+		$startTimeStamp = self::getMillisecond();//请求开始时间
+		$response = self::postXmlCurl($xml, $url, false, $timeOut);
+		$result = WxPayResults::Init($response);
+		self::reportCostTime($url, $startTimeStamp, $result);//上报请求花费时间
+		
+		return $result;
+	}
+	
+	/**
+	 * 
+	 * 撤销订单API接口,WxPayReverse中参数out_trade_no和transaction_id必须填写一个
+	 * appid、mchid、spbill_create_ip、nonce_str不需要填入
+	 * @param WxPayReverse $inputObj
+	 * @param int $timeOut
+	 * @throws WxPayException
+	 */
+	public static function reverse($inputObj, $timeOut = 6)
+	{
+		$url = "https://api.mch.weixin.qq.com/secapi/pay/reverse";
+		//检测必填参数
+		if(!$inputObj->IsOut_trade_noSet() && !$inputObj->IsTransaction_idSet()) {
+			throw new WxPayException("撤销订单API接口中,参数out_trade_no和transaction_id必须填写一个!");
+		}
+		
+		$inputObj->SetAppid(WxPayConfig::APPID);//公众账号ID
+		$inputObj->SetMch_id(WxPayConfig::MCHID);//商户号
+		$inputObj->SetNonce_str(self::getNonceStr());//随机字符串
+		
+		$inputObj->SetSign();//签名
+		$xml = $inputObj->ToXml();
+		
+		$startTimeStamp = self::getMillisecond();//请求开始时间
+		$response = self::postXmlCurl($xml, $url, true, $timeOut);
+		$result = WxPayResults::Init($response);
+		self::reportCostTime($url, $startTimeStamp, $result);//上报请求花费时间
+		
+		return $result;
+	}
+	
+	/**
+	 * 
+	 * 测速上报,该方法内部封装在report中,使用时请注意异常流程
+	 * WxPayReport中interface_url、return_code、result_code、user_ip、execute_time_必填
+	 * appid、mchid、spbill_create_ip、nonce_str不需要填入
+	 * @param WxPayReport $inputObj
+	 * @param int $timeOut
+	 * @throws WxPayException
+	 * @return 成功时返回,其他抛异常
+	 */
+	public static function report($inputObj, $timeOut = 1)
+	{
+		$url = "https://api.mch.weixin.qq.com/payitil/report";
+		//检测必填参数
+		if(!$inputObj->IsInterface_urlSet()) {
+			throw new WxPayException("接口URL,缺少必填参数interface_url!");
+		} if(!$inputObj->IsReturn_codeSet()) {
+			throw new WxPayException("返回状态码,缺少必填参数return_code!");
+		} if(!$inputObj->IsResult_codeSet()) {
+			throw new WxPayException("业务结果,缺少必填参数result_code!");
+		} if(!$inputObj->IsUser_ipSet()) {
+			throw new WxPayException("访问接口IP,缺少必填参数user_ip!");
+		} if(!$inputObj->IsExecute_time_Set()) {
+			throw new WxPayException("接口耗时,缺少必填参数execute_time_!");
+		}
+		$inputObj->SetAppid(WxPayConfig::APPID);//公众账号ID
+		$inputObj->SetMch_id(WxPayConfig::MCHID);//商户号
+		$inputObj->SetUser_ip($_SERVER['REMOTE_ADDR']);//终端ip
+		$inputObj->SetTime(date("YmdHis"));//商户上报时间	 
+		$inputObj->SetNonce_str(self::getNonceStr());//随机字符串
+		
+		$inputObj->SetSign();//签名
+		$xml = $inputObj->ToXml();
+		
+		$startTimeStamp = self::getMillisecond();//请求开始时间
+		$response = self::postXmlCurl($xml, $url, false, $timeOut);
+		return $response;
+	}
+	
+	/**
+	 * 
+	 * 生成二维码规则,模式一生成支付二维码
+	 * appid、mchid、spbill_create_ip、nonce_str不需要填入
+	 * @param WxPayBizPayUrl $inputObj
+	 * @param int $timeOut
+	 * @throws WxPayException
+	 * @return 成功时返回,其他抛异常
+	 */
+	public static function bizpayurl($inputObj, $timeOut = 6)
+	{
+		if(!$inputObj->IsProduct_idSet()){
+			throw new WxPayException("生成二维码,缺少必填参数product_id!");
+		}
+		
+		$inputObj->SetAppid(WxPayConfig::APPID);//公众账号ID
+		$inputObj->SetMch_id(WxPayConfig::MCHID);//商户号
+		$inputObj->SetTime_stamp(time());//时间戳	 
+		$inputObj->SetNonce_str(self::getNonceStr());//随机字符串
+		
+		$inputObj->SetSign();//签名
+		
+		return $inputObj->GetValues();
+	}
+	
+	/**
+	 * 
+	 * 转换短链接
+	 * 该接口主要用于扫码原生支付模式一中的二维码链接转成短链接(weixin://wxpay/s/XXXXXX),
+	 * 减小二维码数据量,提升扫描速度和精确度。
+	 * appid、mchid、spbill_create_ip、nonce_str不需要填入
+	 * @param WxPayShortUrl $inputObj
+	 * @param int $timeOut
+	 * @throws WxPayException
+	 * @return 成功时返回,其他抛异常
+	 */
+	public static function shorturl($inputObj, $timeOut = 6)
+	{
+		$url = "https://api.mch.weixin.qq.com/tools/shorturl";
+		//检测必填参数
+		if(!$inputObj->IsLong_urlSet()) {
+			throw new WxPayException("需要转换的URL,签名用原串,传输需URL encode!");
+		}
+		$inputObj->SetAppid(WxPayConfig::APPID);//公众账号ID
+		$inputObj->SetMch_id(WxPayConfig::MCHID);//商户号
+		$inputObj->SetNonce_str(self::getNonceStr());//随机字符串
+		
+		$inputObj->SetSign();//签名
+		$xml = $inputObj->ToXml();
+		
+		$startTimeStamp = self::getMillisecond();//请求开始时间
+		$response = self::postXmlCurl($xml, $url, false, $timeOut);
+		$result = WxPayResults::Init($response);
+		self::reportCostTime($url, $startTimeStamp, $result);//上报请求花费时间
+		
+		return $result;
+	}
+	
+ 	/**
+ 	 * 
+ 	 * 支付结果通用通知
+ 	 * @param function $callback
+ 	 * 直接回调函数使用方法: notify(you_function);
+ 	 * 回调类成员函数方法:notify(array($this, you_function));
+ 	 * $callback  原型为:function function_name($data){}
+ 	 */
+	public static function notify($callback, &$msg)
+	{
+		//获取通知的数据
+		$xml = $GLOBALS['HTTP_RAW_POST_DATA'];
+		//如果返回成功则验证签名
+		try {
+			$result = WxPayResults::Init($xml);
+		} catch (WxPayException $e){
+			$msg = $e->errorMessage();
+			return false;
+		}
+		
+		return call_user_func($callback, $result);
+	}
+	
+	/**
+	 * 
+	 * 产生随机字符串,不长于32位
+	 * @param int $length
+	 * @return 产生的随机字符串
+	 */
+	public static function getNonceStr($length = 32) 
+	{
+		$chars = "abcdefghijklmnopqrstuvwxyz0123456789";  
+		$str ="";
+		for ( $i = 0; $i < $length; $i++ )  {  
+			$str .= substr($chars, mt_rand(0, strlen($chars)-1), 1);  
+		} 
+		return $str;
+	}
+	
+	/**
+	 * 直接输出xml
+	 * @param string $xml
+	 */
+	public static function replyNotify($xml)
+	{
+		echo $xml;
+	}
+	
+	/**
+	 * 
+	 * 上报数据, 上报的时候将屏蔽所有异常流程
+	 * @param string $usrl
+	 * @param int $startTimeStamp
+	 * @param array $data
+	 */
+	private static function reportCostTime($url, $startTimeStamp, $data)
+	{
+		//如果不需要上报数据
+		if(WxPayConfig::REPORT_LEVENL == 0){
+			return;
+		} 
+		//如果仅失败上报
+		if(WxPayConfig::REPORT_LEVENL == 1 &&
+			 array_key_exists("return_code", $data) &&
+			 $data["return_code"] == "SUCCESS" &&
+			 array_key_exists("result_code", $data) &&
+			 $data["result_code"] == "SUCCESS")
+		 {
+		 	return;
+		 }
+		 
+		//上报逻辑
+		$endTimeStamp = self::getMillisecond();
+		$objInput = new WxPayReport();
+		$objInput->SetInterface_url($url);
+		$objInput->SetExecute_time_($endTimeStamp - $startTimeStamp);
+		//返回状态码
+		if(array_key_exists("return_code", $data)){
+			$objInput->SetReturn_code($data["return_code"]);
+		}
+		//返回信息
+		if(array_key_exists("return_msg", $data)){
+			$objInput->SetReturn_msg($data["return_msg"]);
+		}
+		//业务结果
+		if(array_key_exists("result_code", $data)){
+			$objInput->SetResult_code($data["result_code"]);
+		}
+		//错误代码
+		if(array_key_exists("err_code", $data)){
+			$objInput->SetErr_code($data["err_code"]);
+		}
+		//错误代码描述
+		if(array_key_exists("err_code_des", $data)){
+			$objInput->SetErr_code_des($data["err_code_des"]);
+		}
+		//商户订单号
+		if(array_key_exists("out_trade_no", $data)){
+			$objInput->SetOut_trade_no($data["out_trade_no"]);
+		}
+		//设备号
+		if(array_key_exists("device_info", $data)){
+			$objInput->SetDevice_info($data["device_info"]);
+		}
+		
+		try{
+			self::report($objInput);
+		} catch (WxPayException $e){
+			//不做任何处理
+		}
+	}
+
+	/**
+	 * 以post方式提交xml到对应的接口url
+	 * 
+	 * @param string $xml  需要post的xml数据
+	 * @param string $url  url
+	 * @param bool $useCert 是否需要证书,默认不需要
+	 * @param int $second   url执行超时时间,默认30s
+	 * @throws WxPayException
+	 */
+	private static function postXmlCurl($xml, $url, $useCert = false, $second = 30)
+	{		
+		$ch = curl_init();
+		//设置超时
+		curl_setopt($ch, CURLOPT_TIMEOUT, $second);
+		
+		//如果有配置代理这里就设置代理
+		if(WxPayConfig::CURL_PROXY_HOST != "0.0.0.0" 
+			&& WxPayConfig::CURL_PROXY_PORT != 0){
+			curl_setopt($ch,CURLOPT_PROXY, WxPayConfig::CURL_PROXY_HOST);
+			curl_setopt($ch,CURLOPT_PROXYPORT, WxPayConfig::CURL_PROXY_PORT);
+		}
+		curl_setopt($ch,CURLOPT_URL, $url);
+		curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TRUE);
+		curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2);//严格校验
+		//设置header
+		curl_setopt($ch, CURLOPT_HEADER, FALSE);
+		//要求结果为字符串且输出到屏幕上
+		curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
+	
+		if($useCert == true){
+			//设置证书
+			//使用证书:cert 与 key 分别属于两个.pem文件
+			curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
+			curl_setopt($ch,CURLOPT_SSLCERT, WxPayConfig::SSLCERT_PATH);
+			curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
+			curl_setopt($ch,CURLOPT_SSLKEY, WxPayConfig::SSLKEY_PATH);
+		}
+		//post提交方式
+		curl_setopt($ch, CURLOPT_POST, TRUE);
+		curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
+		//运行curl
+		$data = curl_exec($ch);
+		//返回结果
+		if($data){
+			curl_close($ch);
+			return $data;
+		} else { 
+			$error = curl_errno($ch);
+			curl_close($ch);
+			throw new WxPayException("curl出错,错误码:$error");
+		}
+	}
+	
+	/**
+	 * 获取毫秒级别的时间戳
+	 */
+	private static function getMillisecond()
+	{
+		//获取毫秒的时间戳
+		$time = explode ( " ", microtime () );
+		$time = $time[1] . ($time[0] * 1000);
+		$time2 = explode( ".", $time );
+		$time = $time2[0];
+		return $time;
+	}
+}
+

+ 59 - 0
extend/wxpay/lib/WxPay.Config.php

@@ -0,0 +1,59 @@
+<?php
+/**
+* 	配置账号信息
+*/
+
+class WxPayConfig
+{
+	//=======【基本信息设置】=====================================
+	//
+	/**
+	 * TODO: 修改这里配置为您自己申请的商户信息
+	 * 微信公众号信息配置
+	 * 
+	 * APPID:绑定支付的APPID(必须配置,开户邮件中可查看)
+	 * 
+	 * MCHID:商户号(必须配置,开户邮件中可查看)
+	 * 
+	 * KEY:商户支付密钥,参考开户邮件设置(必须配置,登录商户平台自行设置)
+	 * 设置地址:https://pay.weixin.qq.com/index.php/account/api_cert
+	 * 
+	 * APPSECRET:公众帐号secert(仅JSAPI支付的时候需要配置, 登录公众平台,进入开发者中心可设置),
+	 * 获取地址:https://mp.weixin.qq.com/advanced/advanced?action=dev&t=advanced/dev&token=2005451881&lang=zh_CN
+	 * @var string
+	 */
+	const APPID = 'wx426b3015555a46be';
+	const MCHID = '1900009851';
+	const KEY = '8934e7d15453e97507ef794cf7b0519d';
+	const APPSECRET = '7813490da6f1265e4901ffb80afaa36f';
+	
+	//=======【证书路径设置】=====================================
+	/**
+	 * TODO:设置商户证书路径
+	 * 证书路径,注意应该填写绝对路径(仅退款、撤销订单时需要,可登录商户平台下载,
+	 * API证书下载地址:https://pay.weixin.qq.com/index.php/account/api_cert,下载之前需要安装商户操作证书)
+	 * @var path
+	 */
+	const SSLCERT_PATH = '../cert/apiclient_cert.pem';
+	const SSLKEY_PATH = '../cert/apiclient_key.pem';
+	
+	//=======【curl代理设置】===================================
+	/**
+	 * TODO:这里设置代理机器,只有需要代理的时候才设置,不需要代理,请设置为0.0.0.0和0
+	 * 本例程通过curl使用HTTP POST方法,此处可修改代理服务器,
+	 * 默认CURL_PROXY_HOST=0.0.0.0和CURL_PROXY_PORT=0,此时不开启代理(如有需要才设置)
+	 * @var unknown_type
+	 */
+	const CURL_PROXY_HOST = "0.0.0.0";//"10.152.18.220";
+	const CURL_PROXY_PORT = 0;//8080;
+	
+	//=======【上报信息配置】===================================
+	/**
+	 * TODO:接口调用上报等级,默认紧错误上报(注意:上报超时间为【1s】,上报无论成败【永不抛出异常】,
+	 * 不会影响接口调用流程),开启上报之后,方便微信监控请求调用的质量,建议至少
+	 * 开启错误上报。
+	 * 上报等级,0.关闭上报; 1.仅错误出错上报; 2.全量上报
+	 * @var int
+	 */
+	const REPORT_LEVENL = 1;
+}

+ 2984 - 0
extend/wxpay/lib/WxPay.Data.php

@@ -0,0 +1,2984 @@
+<?php
+/**
+* 2015-06-29 修复签名问题
+**/
+require_once "WxPay.Config.php";
+require_once "WxPay.Exception.php";
+
+/**
+ * 
+ * 数据对象基础类,该类中定义数据类最基本的行为,包括:
+ * 计算/设置/获取签名、输出xml格式的参数、从xml读取数据对象等
+ * @author widyhu
+ *
+ */
+class WxPayDataBase
+{
+	protected $values = array();
+	
+	/**
+	* 设置签名,详见签名生成算法
+	* @param string $value 
+	**/
+	public function SetSign()
+	{
+		$sign = $this->MakeSign();
+		$this->values['sign'] = $sign;
+		return $sign;
+	}
+	
+	/**
+	* 获取签名,详见签名生成算法的值
+	* @return 值
+	**/
+	public function GetSign()
+	{
+		return $this->values['sign'];
+	}
+	
+	/**
+	* 判断签名,详见签名生成算法是否存在
+	* @return true 或 false
+	**/
+	public function IsSignSet()
+	{
+		return array_key_exists('sign', $this->values);
+	}
+
+	/**
+	 * 输出xml字符
+	 * @throws WxPayException
+	**/
+	public function ToXml()
+	{
+		if(!is_array($this->values) 
+			|| count($this->values) <= 0)
+		{
+    		throw new WxPayException("数组数据异常!");
+    	}
+    	
+    	$xml = "<xml>";
+    	foreach ($this->values as $key=>$val)
+    	{
+    		if (is_numeric($val)){
+    			$xml.="<".$key.">".$val."</".$key.">";
+    		}else{
+    			$xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
+    		}
+        }
+        $xml.="</xml>";
+        return $xml; 
+	}
+	
+    /**
+     * 将xml转为array
+     * @param string $xml
+     * @throws WxPayException
+     */
+	public function FromXml($xml)
+	{	
+		if(!$xml){
+			throw new WxPayException("xml数据异常!");
+		}
+        //将XML转为array
+        //禁止引用外部xml实体
+        libxml_disable_entity_loader(true);
+        $this->values = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);		
+		return $this->values;
+	}
+	
+	/**
+	 * 格式化参数格式化成url参数
+	 */
+	public function ToUrlParams()
+	{
+		$buff = "";
+		foreach ($this->values as $k => $v)
+		{
+			if($k != "sign" && $v != "" && !is_array($v)){
+				$buff .= $k . "=" . $v . "&";
+			}
+		}
+		
+		$buff = trim($buff, "&");
+		return $buff;
+	}
+	
+	/**
+	 * 生成签名
+	 * @return 签名,本函数不覆盖sign成员变量,如要设置签名需要调用SetSign方法赋值
+	 */
+	public function MakeSign()
+	{
+		//签名步骤一:按字典序排序参数
+		ksort($this->values);
+		$string = $this->ToUrlParams();
+		//签名步骤二:在string后加入KEY
+		$string = $string . "&key=".WxPayConfig::KEY;
+		//签名步骤三:MD5加密
+		$string = md5($string);
+		//签名步骤四:所有字符转为大写
+		$result = strtoupper($string);
+		return $result;
+	}
+	
+	/**
+	 * 获取设置的值
+	 */
+	public function GetValues()
+	{
+		return $this->values;
+	}
+}
+
+/**
+ * 
+ * 接口调用结果类
+ * @author widyhu
+ *
+ */
+class WxPayResults extends WxPayDataBase
+{
+	/**
+	 * 
+	 * 检测签名
+	 */
+	public function CheckSign()
+	{
+		//fix异常
+		if(!$this->IsSignSet()){
+			throw new WxPayException("签名错误!");
+		}
+		
+		$sign = $this->MakeSign();
+		if($this->GetSign() == $sign){
+			return true;
+		}
+		throw new WxPayException("签名错误!");
+	}
+	
+	/**
+	 * 
+	 * 使用数组初始化
+	 * @param array $array
+	 */
+	public function FromArray($array)
+	{
+		$this->values = $array;
+	}
+	
+	/**
+	 * 
+	 * 使用数组初始化对象
+	 * @param array $array
+	 * @param 是否检测签名 $noCheckSign
+	 */
+	public static function InitFromArray($array, $noCheckSign = false)
+	{
+		$obj = new self();
+		$obj->FromArray($array);
+		if($noCheckSign == false){
+			$obj->CheckSign();
+		}
+        return $obj;
+	}
+	
+	/**
+	 * 
+	 * 设置参数
+	 * @param string $key
+	 * @param string $value
+	 */
+	public function SetData($key, $value)
+	{
+		$this->values[$key] = $value;
+	}
+	
+    /**
+     * 将xml转为array
+     * @param string $xml
+     * @throws WxPayException
+     */
+	public static function Init($xml)
+	{	
+		$obj = new self();
+		$obj->FromXml($xml);
+		//fix bug 2015-06-29
+		if($obj->values['return_code'] != 'SUCCESS'){
+			 return $obj->GetValues();
+		}
+		$obj->CheckSign();
+        return $obj->GetValues();
+	}
+}
+
+/**
+ * 
+ * 回调基础类
+ * @author widyhu
+ *
+ */
+class WxPayNotifyReply extends  WxPayDataBase
+{
+	/**
+	 * 
+	 * 设置错误码 FAIL 或者 SUCCESS
+	 * @param string
+	 */
+	public function SetReturn_code($return_code)
+	{
+		$this->values['return_code'] = $return_code;
+	}
+	
+	/**
+	 * 
+	 * 获取错误码 FAIL 或者 SUCCESS
+	 * @return string $return_code
+	 */
+	public function GetReturn_code()
+	{
+		return $this->values['return_code'];
+	}
+
+	/**
+	 * 
+	 * 设置错误信息
+	 * @param string $return_code
+	 */
+	public function SetReturn_msg($return_msg)
+	{
+		$this->values['return_msg'] = $return_msg;
+	}
+	
+	/**
+	 * 
+	 * 获取错误信息
+	 * @return string
+	 */
+	public function GetReturn_msg()
+	{
+		return $this->values['return_msg'];
+	}
+	
+	/**
+	 * 
+	 * 设置返回参数
+	 * @param string $key
+	 * @param string $value
+	 */
+	public function SetData($key, $value)
+	{
+		$this->values[$key] = $value;
+	}
+}
+
+/**
+ * 
+ * 统一下单输入对象
+ * @author widyhu
+ *
+ */
+class WxPayUnifiedOrder extends WxPayDataBase
+{	
+	/**
+	* 设置微信分配的公众账号ID
+	* @param string $value 
+	**/
+	public function SetAppid($value)
+	{
+		$this->values['appid'] = $value;
+	}
+	/**
+	* 获取微信分配的公众账号ID的值
+	* @return 值
+	**/
+	public function GetAppid()
+	{
+		return $this->values['appid'];
+	}
+	/**
+	* 判断微信分配的公众账号ID是否存在
+	* @return true 或 false
+	**/
+	public function IsAppidSet()
+	{
+		return array_key_exists('appid', $this->values);
+	}
+
+
+	/**
+	* 设置微信支付分配的商户号
+	* @param string $value 
+	**/
+	public function SetMch_id($value)
+	{
+		$this->values['mch_id'] = $value;
+	}
+	/**
+	* 获取微信支付分配的商户号的值
+	* @return 值
+	**/
+	public function GetMch_id()
+	{
+		return $this->values['mch_id'];
+	}
+	/**
+	* 判断微信支付分配的商户号是否存在
+	* @return true 或 false
+	**/
+	public function IsMch_idSet()
+	{
+		return array_key_exists('mch_id', $this->values);
+	}
+
+
+	/**
+	* 设置微信支付分配的终端设备号,商户自定义
+	* @param string $value 
+	**/
+	public function SetDevice_info($value)
+	{
+		$this->values['device_info'] = $value;
+	}
+	/**
+	* 获取微信支付分配的终端设备号,商户自定义的值
+	* @return 值
+	**/
+	public function GetDevice_info()
+	{
+		return $this->values['device_info'];
+	}
+	/**
+	* 判断微信支付分配的终端设备号,商户自定义是否存在
+	* @return true 或 false
+	**/
+	public function IsDevice_infoSet()
+	{
+		return array_key_exists('device_info', $this->values);
+	}
+
+
+	/**
+	* 设置随机字符串,不长于32位。推荐随机数生成算法
+	* @param string $value 
+	**/
+	public function SetNonce_str($value)
+	{
+		$this->values['nonce_str'] = $value;
+	}
+	/**
+	* 获取随机字符串,不长于32位。推荐随机数生成算法的值
+	* @return 值
+	**/
+	public function GetNonce_str()
+	{
+		return $this->values['nonce_str'];
+	}
+	/**
+	* 判断随机字符串,不长于32位。推荐随机数生成算法是否存在
+	* @return true 或 false
+	**/
+	public function IsNonce_strSet()
+	{
+		return array_key_exists('nonce_str', $this->values);
+	}
+
+	/**
+	* 设置商品或支付单简要描述
+	* @param string $value 
+	**/
+	public function SetBody($value)
+	{
+		$this->values['body'] = $value;
+	}
+	/**
+	* 获取商品或支付单简要描述的值
+	* @return 值
+	**/
+	public function GetBody()
+	{
+		return $this->values['body'];
+	}
+	/**
+	* 判断商品或支付单简要描述是否存在
+	* @return true 或 false
+	**/
+	public function IsBodySet()
+	{
+		return array_key_exists('body', $this->values);
+	}
+
+
+	/**
+	* 设置商品名称明细列表
+	* @param string $value 
+	**/
+	public function SetDetail($value)
+	{
+		$this->values['detail'] = $value;
+	}
+	/**
+	* 获取商品名称明细列表的值
+	* @return 值
+	**/
+	public function GetDetail()
+	{
+		return $this->values['detail'];
+	}
+	/**
+	* 判断商品名称明细列表是否存在
+	* @return true 或 false
+	**/
+	public function IsDetailSet()
+	{
+		return array_key_exists('detail', $this->values);
+	}
+
+
+	/**
+	* 设置附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据
+	* @param string $value 
+	**/
+	public function SetAttach($value)
+	{
+		$this->values['attach'] = $value;
+	}
+	/**
+	* 获取附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据的值
+	* @return 值
+	**/
+	public function GetAttach()
+	{
+		return $this->values['attach'];
+	}
+	/**
+	* 判断附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据是否存在
+	* @return true 或 false
+	**/
+	public function IsAttachSet()
+	{
+		return array_key_exists('attach', $this->values);
+	}
+
+
+	/**
+	* 设置商户系统内部的订单号,32个字符内、可包含字母, 其他说明见商户订单号
+	* @param string $value 
+	**/
+	public function SetOut_trade_no($value)
+	{
+		$this->values['out_trade_no'] = $value;
+	}
+	/**
+	* 获取商户系统内部的订单号,32个字符内、可包含字母, 其他说明见商户订单号的值
+	* @return 值
+	**/
+	public function GetOut_trade_no()
+	{
+		return $this->values['out_trade_no'];
+	}
+	/**
+	* 判断商户系统内部的订单号,32个字符内、可包含字母, 其他说明见商户订单号是否存在
+	* @return true 或 false
+	**/
+	public function IsOut_trade_noSet()
+	{
+		return array_key_exists('out_trade_no', $this->values);
+	}
+
+
+	/**
+	* 设置符合ISO 4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型
+	* @param string $value 
+	**/
+	public function SetFee_type($value)
+	{
+		$this->values['fee_type'] = $value;
+	}
+	/**
+	* 获取符合ISO 4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型的值
+	* @return 值
+	**/
+	public function GetFee_type()
+	{
+		return $this->values['fee_type'];
+	}
+	/**
+	* 判断符合ISO 4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型是否存在
+	* @return true 或 false
+	**/
+	public function IsFee_typeSet()
+	{
+		return array_key_exists('fee_type', $this->values);
+	}
+
+
+	/**
+	* 设置订单总金额,只能为整数,详见支付金额
+	* @param string $value 
+	**/
+	public function SetTotal_fee($value)
+	{
+		$this->values['total_fee'] = $value;
+	}
+	/**
+	* 获取订单总金额,只能为整数,详见支付金额的值
+	* @return 值
+	**/
+	public function GetTotal_fee()
+	{
+		return $this->values['total_fee'];
+	}
+	/**
+	* 判断订单总金额,只能为整数,详见支付金额是否存在
+	* @return true 或 false
+	**/
+	public function IsTotal_feeSet()
+	{
+		return array_key_exists('total_fee', $this->values);
+	}
+
+
+	/**
+	* 设置APP和网页支付提交用户端ip,Native支付填调用微信支付API的机器IP。
+	* @param string $value 
+	**/
+	public function SetSpbill_create_ip($value)
+	{
+		$this->values['spbill_create_ip'] = $value;
+	}
+	/**
+	* 获取APP和网页支付提交用户端ip,Native支付填调用微信支付API的机器IP。的值
+	* @return 值
+	**/
+	public function GetSpbill_create_ip()
+	{
+		return $this->values['spbill_create_ip'];
+	}
+	/**
+	* 判断APP和网页支付提交用户端ip,Native支付填调用微信支付API的机器IP。是否存在
+	* @return true 或 false
+	**/
+	public function IsSpbill_create_ipSet()
+	{
+		return array_key_exists('spbill_create_ip', $this->values);
+	}
+
+
+	/**
+	* 设置订单生成时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则
+	* @param string $value 
+	**/
+	public function SetTime_start($value)
+	{
+		$this->values['time_start'] = $value;
+	}
+	/**
+	* 获取订单生成时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则的值
+	* @return 值
+	**/
+	public function GetTime_start()
+	{
+		return $this->values['time_start'];
+	}
+	/**
+	* 判断订单生成时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则是否存在
+	* @return true 或 false
+	**/
+	public function IsTime_startSet()
+	{
+		return array_key_exists('time_start', $this->values);
+	}
+
+
+	/**
+	* 设置订单失效时间,格式为yyyyMMddHHmmss,如2009年12月27日9点10分10秒表示为20091227091010。其他详见时间规则
+	* @param string $value 
+	**/
+	public function SetTime_expire($value)
+	{
+		$this->values['time_expire'] = $value;
+	}
+	/**
+	* 获取订单失效时间,格式为yyyyMMddHHmmss,如2009年12月27日9点10分10秒表示为20091227091010。其他详见时间规则的值
+	* @return 值
+	**/
+	public function GetTime_expire()
+	{
+		return $this->values['time_expire'];
+	}
+	/**
+	* 判断订单失效时间,格式为yyyyMMddHHmmss,如2009年12月27日9点10分10秒表示为20091227091010。其他详见时间规则是否存在
+	* @return true 或 false
+	**/
+	public function IsTime_expireSet()
+	{
+		return array_key_exists('time_expire', $this->values);
+	}
+
+
+	/**
+	* 设置商品标记,代金券或立减优惠功能的参数,说明详见代金券或立减优惠
+	* @param string $value 
+	**/
+	public function SetGoods_tag($value)
+	{
+		$this->values['goods_tag'] = $value;
+	}
+	/**
+	* 获取商品标记,代金券或立减优惠功能的参数,说明详见代金券或立减优惠的值
+	* @return 值
+	**/
+	public function GetGoods_tag()
+	{
+		return $this->values['goods_tag'];
+	}
+	/**
+	* 判断商品标记,代金券或立减优惠功能的参数,说明详见代金券或立减优惠是否存在
+	* @return true 或 false
+	**/
+	public function IsGoods_tagSet()
+	{
+		return array_key_exists('goods_tag', $this->values);
+	}
+
+
+	/**
+	* 设置接收微信支付异步通知回调地址
+	* @param string $value 
+	**/
+	public function SetNotify_url($value)
+	{
+		$this->values['notify_url'] = $value;
+	}
+	/**
+	* 获取接收微信支付异步通知回调地址的值
+	* @return 值
+	**/
+	public function GetNotify_url()
+	{
+		return $this->values['notify_url'];
+	}
+	/**
+	* 判断接收微信支付异步通知回调地址是否存在
+	* @return true 或 false
+	**/
+	public function IsNotify_urlSet()
+	{
+		return array_key_exists('notify_url', $this->values);
+	}
+
+
+	/**
+	* 设置取值如下:JSAPI,NATIVE,APP,详细说明见参数规定
+	* @param string $value 
+	**/
+	public function SetTrade_type($value)
+	{
+		$this->values['trade_type'] = $value;
+	}
+	/**
+	* 获取取值如下:JSAPI,NATIVE,APP,详细说明见参数规定的值
+	* @return 值
+	**/
+	public function GetTrade_type()
+	{
+		return $this->values['trade_type'];
+	}
+	/**
+	* 判断取值如下:JSAPI,NATIVE,APP,详细说明见参数规定是否存在
+	* @return true 或 false
+	**/
+	public function IsTrade_typeSet()
+	{
+		return array_key_exists('trade_type', $this->values);
+	}
+
+
+	/**
+	* 设置trade_type=NATIVE,此参数必传。此id为二维码中包含的商品ID,商户自行定义。
+	* @param string $value 
+	**/
+	public function SetProduct_id($value)
+	{
+		$this->values['product_id'] = $value;
+	}
+	/**
+	* 获取trade_type=NATIVE,此参数必传。此id为二维码中包含的商品ID,商户自行定义。的值
+	* @return 值
+	**/
+	public function GetProduct_id()
+	{
+		return $this->values['product_id'];
+	}
+	/**
+	* 判断trade_type=NATIVE,此参数必传。此id为二维码中包含的商品ID,商户自行定义。是否存在
+	* @return true 或 false
+	**/
+	public function IsProduct_idSet()
+	{
+		return array_key_exists('product_id', $this->values);
+	}
+
+
+	/**
+	* 设置trade_type=JSAPI,此参数必传,用户在商户appid下的唯一标识。下单前需要调用【网页授权获取用户信息】接口获取到用户的Openid。 
+	* @param string $value 
+	**/
+	public function SetOpenid($value)
+	{
+		$this->values['openid'] = $value;
+	}
+	/**
+	* 获取trade_type=JSAPI,此参数必传,用户在商户appid下的唯一标识。下单前需要调用【网页授权获取用户信息】接口获取到用户的Openid。 的值
+	* @return 值
+	**/
+	public function GetOpenid()
+	{
+		return $this->values['openid'];
+	}
+	/**
+	* 判断trade_type=JSAPI,此参数必传,用户在商户appid下的唯一标识。下单前需要调用【网页授权获取用户信息】接口获取到用户的Openid。 是否存在
+	* @return true 或 false
+	**/
+	public function IsOpenidSet()
+	{
+		return array_key_exists('openid', $this->values);
+	}
+}
+
+/**
+ * 
+ * 订单查询输入对象
+ * @author widyhu
+ *
+ */
+class WxPayOrderQuery extends WxPayDataBase
+{
+	/**
+	* 设置微信分配的公众账号ID
+	* @param string $value 
+	**/
+	public function SetAppid($value)
+	{
+		$this->values['appid'] = $value;
+	}
+	/**
+	* 获取微信分配的公众账号ID的值
+	* @return 值
+	**/
+	public function GetAppid()
+	{
+		return $this->values['appid'];
+	}
+	/**
+	* 判断微信分配的公众账号ID是否存在
+	* @return true 或 false
+	**/
+	public function IsAppidSet()
+	{
+		return array_key_exists('appid', $this->values);
+	}
+
+
+	/**
+	* 设置微信支付分配的商户号
+	* @param string $value 
+	**/
+	public function SetMch_id($value)
+	{
+		$this->values['mch_id'] = $value;
+	}
+	/**
+	* 获取微信支付分配的商户号的值
+	* @return 值
+	**/
+	public function GetMch_id()
+	{
+		return $this->values['mch_id'];
+	}
+	/**
+	* 判断微信支付分配的商户号是否存在
+	* @return true 或 false
+	**/
+	public function IsMch_idSet()
+	{
+		return array_key_exists('mch_id', $this->values);
+	}
+
+
+	/**
+	* 设置微信的订单号,优先使用
+	* @param string $value 
+	**/
+	public function SetTransaction_id($value)
+	{
+		$this->values['transaction_id'] = $value;
+	}
+	/**
+	* 获取微信的订单号,优先使用的值
+	* @return 值
+	**/
+	public function GetTransaction_id()
+	{
+		return $this->values['transaction_id'];
+	}
+	/**
+	* 判断微信的订单号,优先使用是否存在
+	* @return true 或 false
+	**/
+	public function IsTransaction_idSet()
+	{
+		return array_key_exists('transaction_id', $this->values);
+	}
+
+
+	/**
+	* 设置商户系统内部的订单号,当没提供transaction_id时需要传这个。
+	* @param string $value 
+	**/
+	public function SetOut_trade_no($value)
+	{
+		$this->values['out_trade_no'] = $value;
+	}
+	/**
+	* 获取商户系统内部的订单号,当没提供transaction_id时需要传这个。的值
+	* @return 值
+	**/
+	public function GetOut_trade_no()
+	{
+		return $this->values['out_trade_no'];
+	}
+	/**
+	* 判断商户系统内部的订单号,当没提供transaction_id时需要传这个。是否存在
+	* @return true 或 false
+	**/
+	public function IsOut_trade_noSet()
+	{
+		return array_key_exists('out_trade_no', $this->values);
+	}
+
+
+	/**
+	* 设置随机字符串,不长于32位。推荐随机数生成算法
+	* @param string $value 
+	**/
+	public function SetNonce_str($value)
+	{
+		$this->values['nonce_str'] = $value;
+	}
+	/**
+	* 获取随机字符串,不长于32位。推荐随机数生成算法的值
+	* @return 值
+	**/
+	public function GetNonce_str()
+	{
+		return $this->values['nonce_str'];
+	}
+	/**
+	* 判断随机字符串,不长于32位。推荐随机数生成算法是否存在
+	* @return true 或 false
+	**/
+	public function IsNonce_strSet()
+	{
+		return array_key_exists('nonce_str', $this->values);
+	}
+}
+
+/**
+ * 
+ * 关闭订单输入对象
+ * @author widyhu
+ *
+ */
+class WxPayCloseOrder extends WxPayDataBase
+{
+	/**
+	* 设置微信分配的公众账号ID
+	* @param string $value 
+	**/
+	public function SetAppid($value)
+	{
+		$this->values['appid'] = $value;
+	}
+	/**
+	* 获取微信分配的公众账号ID的值
+	* @return 值
+	**/
+	public function GetAppid()
+	{
+		return $this->values['appid'];
+	}
+	/**
+	* 判断微信分配的公众账号ID是否存在
+	* @return true 或 false
+	**/
+	public function IsAppidSet()
+	{
+		return array_key_exists('appid', $this->values);
+	}
+
+
+	/**
+	* 设置微信支付分配的商户号
+	* @param string $value 
+	**/
+	public function SetMch_id($value)
+	{
+		$this->values['mch_id'] = $value;
+	}
+	/**
+	* 获取微信支付分配的商户号的值
+	* @return 值
+	**/
+	public function GetMch_id()
+	{
+		return $this->values['mch_id'];
+	}
+	/**
+	* 判断微信支付分配的商户号是否存在
+	* @return true 或 false
+	**/
+	public function IsMch_idSet()
+	{
+		return array_key_exists('mch_id', $this->values);
+	}
+
+
+	/**
+	* 设置商户系统内部的订单号
+	* @param string $value 
+	**/
+	public function SetOut_trade_no($value)
+	{
+		$this->values['out_trade_no'] = $value;
+	}
+	/**
+	* 获取商户系统内部的订单号的值
+	* @return 值
+	**/
+	public function GetOut_trade_no()
+	{
+		return $this->values['out_trade_no'];
+	}
+	/**
+	* 判断商户系统内部的订单号是否存在
+	* @return true 或 false
+	**/
+	public function IsOut_trade_noSet()
+	{
+		return array_key_exists('out_trade_no', $this->values);
+	}
+
+
+	/**
+	* 设置商户系统内部的订单号,32个字符内、可包含字母, 其他说明见商户订单号
+	* @param string $value 
+	**/
+	public function SetNonce_str($value)
+	{
+		$this->values['nonce_str'] = $value;
+	}
+	/**
+	* 获取商户系统内部的订单号,32个字符内、可包含字母, 其他说明见商户订单号的值
+	* @return 值
+	**/
+	public function GetNonce_str()
+	{
+		return $this->values['nonce_str'];
+	}
+	/**
+	* 判断商户系统内部的订单号,32个字符内、可包含字母, 其他说明见商户订单号是否存在
+	* @return true 或 false
+	**/
+	public function IsNonce_strSet()
+	{
+		return array_key_exists('nonce_str', $this->values);
+	}
+}
+
+/**
+ * 
+ * 提交退款输入对象
+ * @author widyhu
+ *
+ */
+class WxPayRefund extends WxPayDataBase
+{
+	/**
+	* 设置微信分配的公众账号ID
+	* @param string $value 
+	**/
+	public function SetAppid($value)
+	{
+		$this->values['appid'] = $value;
+	}
+	/**
+	* 获取微信分配的公众账号ID的值
+	* @return 值
+	**/
+	public function GetAppid()
+	{
+		return $this->values['appid'];
+	}
+	/**
+	* 判断微信分配的公众账号ID是否存在
+	* @return true 或 false
+	**/
+	public function IsAppidSet()
+	{
+		return array_key_exists('appid', $this->values);
+	}
+
+
+	/**
+	* 设置微信支付分配的商户号
+	* @param string $value 
+	**/
+	public function SetMch_id($value)
+	{
+		$this->values['mch_id'] = $value;
+	}
+	/**
+	* 获取微信支付分配的商户号的值
+	* @return 值
+	**/
+	public function GetMch_id()
+	{
+		return $this->values['mch_id'];
+	}
+	/**
+	* 判断微信支付分配的商户号是否存在
+	* @return true 或 false
+	**/
+	public function IsMch_idSet()
+	{
+		return array_key_exists('mch_id', $this->values);
+	}
+
+
+	/**
+	* 设置微信支付分配的终端设备号,与下单一致
+	* @param string $value 
+	**/
+	public function SetDevice_info($value)
+	{
+		$this->values['device_info'] = $value;
+	}
+	/**
+	* 获取微信支付分配的终端设备号,与下单一致的值
+	* @return 值
+	**/
+	public function GetDevice_info()
+	{
+		return $this->values['device_info'];
+	}
+	/**
+	* 判断微信支付分配的终端设备号,与下单一致是否存在
+	* @return true 或 false
+	**/
+	public function IsDevice_infoSet()
+	{
+		return array_key_exists('device_info', $this->values);
+	}
+
+
+	/**
+	* 设置随机字符串,不长于32位。推荐随机数生成算法
+	* @param string $value 
+	**/
+	public function SetNonce_str($value)
+	{
+		$this->values['nonce_str'] = $value;
+	}
+	/**
+	* 获取随机字符串,不长于32位。推荐随机数生成算法的值
+	* @return 值
+	**/
+	public function GetNonce_str()
+	{
+		return $this->values['nonce_str'];
+	}
+	/**
+	* 判断随机字符串,不长于32位。推荐随机数生成算法是否存在
+	* @return true 或 false
+	**/
+	public function IsNonce_strSet()
+	{
+		return array_key_exists('nonce_str', $this->values);
+	}
+
+	/**
+	* 设置微信订单号
+	* @param string $value 
+	**/
+	public function SetTransaction_id($value)
+	{
+		$this->values['transaction_id'] = $value;
+	}
+	/**
+	* 获取微信订单号的值
+	* @return 值
+	**/
+	public function GetTransaction_id()
+	{
+		return $this->values['transaction_id'];
+	}
+	/**
+	* 判断微信订单号是否存在
+	* @return true 或 false
+	**/
+	public function IsTransaction_idSet()
+	{
+		return array_key_exists('transaction_id', $this->values);
+	}
+
+
+	/**
+	* 设置商户系统内部的订单号,transaction_id、out_trade_no二选一,如果同时存在优先级:transaction_id> out_trade_no
+	* @param string $value 
+	**/
+	public function SetOut_trade_no($value)
+	{
+		$this->values['out_trade_no'] = $value;
+	}
+	/**
+	* 获取商户系统内部的订单号,transaction_id、out_trade_no二选一,如果同时存在优先级:transaction_id> out_trade_no的值
+	* @return 值
+	**/
+	public function GetOut_trade_no()
+	{
+		return $this->values['out_trade_no'];
+	}
+	/**
+	* 判断商户系统内部的订单号,transaction_id、out_trade_no二选一,如果同时存在优先级:transaction_id> out_trade_no是否存在
+	* @return true 或 false
+	**/
+	public function IsOut_trade_noSet()
+	{
+		return array_key_exists('out_trade_no', $this->values);
+	}
+
+
+	/**
+	* 设置商户系统内部的退款单号,商户系统内部唯一,同一退款单号多次请求只退一笔
+	* @param string $value 
+	**/
+	public function SetOut_refund_no($value)
+	{
+		$this->values['out_refund_no'] = $value;
+	}
+	/**
+	* 获取商户系统内部的退款单号,商户系统内部唯一,同一退款单号多次请求只退一笔的值
+	* @return 值
+	**/
+	public function GetOut_refund_no()
+	{
+		return $this->values['out_refund_no'];
+	}
+	/**
+	* 判断商户系统内部的退款单号,商户系统内部唯一,同一退款单号多次请求只退一笔是否存在
+	* @return true 或 false
+	**/
+	public function IsOut_refund_noSet()
+	{
+		return array_key_exists('out_refund_no', $this->values);
+	}
+
+
+	/**
+	* 设置订单总金额,单位为分,只能为整数,详见支付金额
+	* @param string $value 
+	**/
+	public function SetTotal_fee($value)
+	{
+		$this->values['total_fee'] = $value;
+	}
+	/**
+	* 获取订单总金额,单位为分,只能为整数,详见支付金额的值
+	* @return 值
+	**/
+	public function GetTotal_fee()
+	{
+		return $this->values['total_fee'];
+	}
+	/**
+	* 判断订单总金额,单位为分,只能为整数,详见支付金额是否存在
+	* @return true 或 false
+	**/
+	public function IsTotal_feeSet()
+	{
+		return array_key_exists('total_fee', $this->values);
+	}
+
+
+	/**
+	* 设置退款总金额,订单总金额,单位为分,只能为整数,详见支付金额
+	* @param string $value 
+	**/
+	public function SetRefund_fee($value)
+	{
+		$this->values['refund_fee'] = $value;
+	}
+	/**
+	* 获取退款总金额,订单总金额,单位为分,只能为整数,详见支付金额的值
+	* @return 值
+	**/
+	public function GetRefund_fee()
+	{
+		return $this->values['refund_fee'];
+	}
+	/**
+	* 判断退款总金额,订单总金额,单位为分,只能为整数,详见支付金额是否存在
+	* @return true 或 false
+	**/
+	public function IsRefund_feeSet()
+	{
+		return array_key_exists('refund_fee', $this->values);
+	}
+
+
+	/**
+	* 设置货币类型,符合ISO 4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型
+	* @param string $value 
+	**/
+	public function SetRefund_fee_type($value)
+	{
+		$this->values['refund_fee_type'] = $value;
+	}
+	/**
+	* 获取货币类型,符合ISO 4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型的值
+	* @return 值
+	**/
+	public function GetRefund_fee_type()
+	{
+		return $this->values['refund_fee_type'];
+	}
+	/**
+	* 判断货币类型,符合ISO 4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型是否存在
+	* @return true 或 false
+	**/
+	public function IsRefund_fee_typeSet()
+	{
+		return array_key_exists('refund_fee_type', $this->values);
+	}
+
+
+	/**
+	* 设置操作员帐号, 默认为商户号
+	* @param string $value 
+	**/
+	public function SetOp_user_id($value)
+	{
+		$this->values['op_user_id'] = $value;
+	}
+	/**
+	* 获取操作员帐号, 默认为商户号的值
+	* @return 值
+	**/
+	public function GetOp_user_id()
+	{
+		return $this->values['op_user_id'];
+	}
+	/**
+	* 判断操作员帐号, 默认为商户号是否存在
+	* @return true 或 false
+	**/
+	public function IsOp_user_idSet()
+	{
+		return array_key_exists('op_user_id', $this->values);
+	}
+}
+
+/**
+ * 
+ * 退款查询输入对象
+ * @author widyhu
+ *
+ */
+class WxPayRefundQuery extends WxPayDataBase
+{
+	/**
+	* 设置微信分配的公众账号ID
+	* @param string $value 
+	**/
+	public function SetAppid($value)
+	{
+		$this->values['appid'] = $value;
+	}
+	/**
+	* 获取微信分配的公众账号ID的值
+	* @return 值
+	**/
+	public function GetAppid()
+	{
+		return $this->values['appid'];
+	}
+	/**
+	* 判断微信分配的公众账号ID是否存在
+	* @return true 或 false
+	**/
+	public function IsAppidSet()
+	{
+		return array_key_exists('appid', $this->values);
+	}
+
+
+	/**
+	* 设置微信支付分配的商户号
+	* @param string $value 
+	**/
+	public function SetMch_id($value)
+	{
+		$this->values['mch_id'] = $value;
+	}
+	/**
+	* 获取微信支付分配的商户号的值
+	* @return 值
+	**/
+	public function GetMch_id()
+	{
+		return $this->values['mch_id'];
+	}
+	/**
+	* 判断微信支付分配的商户号是否存在
+	* @return true 或 false
+	**/
+	public function IsMch_idSet()
+	{
+		return array_key_exists('mch_id', $this->values);
+	}
+
+
+	/**
+	* 设置微信支付分配的终端设备号
+	* @param string $value 
+	**/
+	public function SetDevice_info($value)
+	{
+		$this->values['device_info'] = $value;
+	}
+	/**
+	* 获取微信支付分配的终端设备号的值
+	* @return 值
+	**/
+	public function GetDevice_info()
+	{
+		return $this->values['device_info'];
+	}
+	/**
+	* 判断微信支付分配的终端设备号是否存在
+	* @return true 或 false
+	**/
+	public function IsDevice_infoSet()
+	{
+		return array_key_exists('device_info', $this->values);
+	}
+
+
+	/**
+	* 设置随机字符串,不长于32位。推荐随机数生成算法
+	* @param string $value 
+	**/
+	public function SetNonce_str($value)
+	{
+		$this->values['nonce_str'] = $value;
+	}
+	/**
+	* 获取随机字符串,不长于32位。推荐随机数生成算法的值
+	* @return 值
+	**/
+	public function GetNonce_str()
+	{
+		return $this->values['nonce_str'];
+	}
+	/**
+	* 判断随机字符串,不长于32位。推荐随机数生成算法是否存在
+	* @return true 或 false
+	**/
+	public function IsNonce_strSet()
+	{
+		return array_key_exists('nonce_str', $this->values);
+	}
+
+	/**
+	* 设置微信订单号
+	* @param string $value 
+	**/
+	public function SetTransaction_id($value)
+	{
+		$this->values['transaction_id'] = $value;
+	}
+	/**
+	* 获取微信订单号的值
+	* @return 值
+	**/
+	public function GetTransaction_id()
+	{
+		return $this->values['transaction_id'];
+	}
+	/**
+	* 判断微信订单号是否存在
+	* @return true 或 false
+	**/
+	public function IsTransaction_idSet()
+	{
+		return array_key_exists('transaction_id', $this->values);
+	}
+
+
+	/**
+	* 设置商户系统内部的订单号
+	* @param string $value 
+	**/
+	public function SetOut_trade_no($value)
+	{
+		$this->values['out_trade_no'] = $value;
+	}
+	/**
+	* 获取商户系统内部的订单号的值
+	* @return 值
+	**/
+	public function GetOut_trade_no()
+	{
+		return $this->values['out_trade_no'];
+	}
+	/**
+	* 判断商户系统内部的订单号是否存在
+	* @return true 或 false
+	**/
+	public function IsOut_trade_noSet()
+	{
+		return array_key_exists('out_trade_no', $this->values);
+	}
+
+
+	/**
+	* 设置商户退款单号
+	* @param string $value 
+	**/
+	public function SetOut_refund_no($value)
+	{
+		$this->values['out_refund_no'] = $value;
+	}
+	/**
+	* 获取商户退款单号的值
+	* @return 值
+	**/
+	public function GetOut_refund_no()
+	{
+		return $this->values['out_refund_no'];
+	}
+	/**
+	* 判断商户退款单号是否存在
+	* @return true 或 false
+	**/
+	public function IsOut_refund_noSet()
+	{
+		return array_key_exists('out_refund_no', $this->values);
+	}
+
+
+	/**
+	* 设置微信退款单号refund_id、out_refund_no、out_trade_no、transaction_id四个参数必填一个,如果同时存在优先级为:refund_id>out_refund_no>transaction_id>out_trade_no
+	* @param string $value 
+	**/
+	public function SetRefund_id($value)
+	{
+		$this->values['refund_id'] = $value;
+	}
+	/**
+	* 获取微信退款单号refund_id、out_refund_no、out_trade_no、transaction_id四个参数必填一个,如果同时存在优先级为:refund_id>out_refund_no>transaction_id>out_trade_no的值
+	* @return 值
+	**/
+	public function GetRefund_id()
+	{
+		return $this->values['refund_id'];
+	}
+	/**
+	* 判断微信退款单号refund_id、out_refund_no、out_trade_no、transaction_id四个参数必填一个,如果同时存在优先级为:refund_id>out_refund_no>transaction_id>out_trade_no是否存在
+	* @return true 或 false
+	**/
+	public function IsRefund_idSet()
+	{
+		return array_key_exists('refund_id', $this->values);
+	}
+}
+
+/**
+ * 
+ * 下载对账单输入对象
+ * @author widyhu
+ *
+ */
+class WxPayDownloadBill extends WxPayDataBase
+{
+	/**
+	* 设置微信分配的公众账号ID
+	* @param string $value 
+	**/
+	public function SetAppid($value)
+	{
+		$this->values['appid'] = $value;
+	}
+	/**
+	* 获取微信分配的公众账号ID的值
+	* @return 值
+	**/
+	public function GetAppid()
+	{
+		return $this->values['appid'];
+	}
+	/**
+	* 判断微信分配的公众账号ID是否存在
+	* @return true 或 false
+	**/
+	public function IsAppidSet()
+	{
+		return array_key_exists('appid', $this->values);
+	}
+
+
+	/**
+	* 设置微信支付分配的商户号
+	* @param string $value 
+	**/
+	public function SetMch_id($value)
+	{
+		$this->values['mch_id'] = $value;
+	}
+	/**
+	* 获取微信支付分配的商户号的值
+	* @return 值
+	**/
+	public function GetMch_id()
+	{
+		return $this->values['mch_id'];
+	}
+	/**
+	* 判断微信支付分配的商户号是否存在
+	* @return true 或 false
+	**/
+	public function IsMch_idSet()
+	{
+		return array_key_exists('mch_id', $this->values);
+	}
+
+
+	/**
+	* 设置微信支付分配的终端设备号,填写此字段,只下载该设备号的对账单
+	* @param string $value 
+	**/
+	public function SetDevice_info($value)
+	{
+		$this->values['device_info'] = $value;
+	}
+	/**
+	* 获取微信支付分配的终端设备号,填写此字段,只下载该设备号的对账单的值
+	* @return 值
+	**/
+	public function GetDevice_info()
+	{
+		return $this->values['device_info'];
+	}
+	/**
+	* 判断微信支付分配的终端设备号,填写此字段,只下载该设备号的对账单是否存在
+	* @return true 或 false
+	**/
+	public function IsDevice_infoSet()
+	{
+		return array_key_exists('device_info', $this->values);
+	}
+
+
+	/**
+	* 设置随机字符串,不长于32位。推荐随机数生成算法
+	* @param string $value 
+	**/
+	public function SetNonce_str($value)
+	{
+		$this->values['nonce_str'] = $value;
+	}
+	/**
+	* 获取随机字符串,不长于32位。推荐随机数生成算法的值
+	* @return 值
+	**/
+	public function GetNonce_str()
+	{
+		return $this->values['nonce_str'];
+	}
+	/**
+	* 判断随机字符串,不长于32位。推荐随机数生成算法是否存在
+	* @return true 或 false
+	**/
+	public function IsNonce_strSet()
+	{
+		return array_key_exists('nonce_str', $this->values);
+	}
+
+	/**
+	* 设置下载对账单的日期,格式:20140603
+	* @param string $value 
+	**/
+	public function SetBill_date($value)
+	{
+		$this->values['bill_date'] = $value;
+	}
+	/**
+	* 获取下载对账单的日期,格式:20140603的值
+	* @return 值
+	**/
+	public function GetBill_date()
+	{
+		return $this->values['bill_date'];
+	}
+	/**
+	* 判断下载对账单的日期,格式:20140603是否存在
+	* @return true 或 false
+	**/
+	public function IsBill_dateSet()
+	{
+		return array_key_exists('bill_date', $this->values);
+	}
+
+
+	/**
+	* 设置ALL,返回当日所有订单信息,默认值SUCCESS,返回当日成功支付的订单REFUND,返回当日退款订单REVOKED,已撤销的订单
+	* @param string $value 
+	**/
+	public function SetBill_type($value)
+	{
+		$this->values['bill_type'] = $value;
+	}
+	/**
+	* 获取ALL,返回当日所有订单信息,默认值SUCCESS,返回当日成功支付的订单REFUND,返回当日退款订单REVOKED,已撤销的订单的值
+	* @return 值
+	**/
+	public function GetBill_type()
+	{
+		return $this->values['bill_type'];
+	}
+	/**
+	* 判断ALL,返回当日所有订单信息,默认值SUCCESS,返回当日成功支付的订单REFUND,返回当日退款订单REVOKED,已撤销的订单是否存在
+	* @return true 或 false
+	**/
+	public function IsBill_typeSet()
+	{
+		return array_key_exists('bill_type', $this->values);
+	}
+}
+
+/**
+ * 
+ * 测速上报输入对象
+ * @author widyhu
+ *
+ */
+class WxPayReport extends WxPayDataBase
+{
+	/**
+	* 设置微信分配的公众账号ID
+	* @param string $value 
+	**/
+	public function SetAppid($value)
+	{
+		$this->values['appid'] = $value;
+	}
+	/**
+	* 获取微信分配的公众账号ID的值
+	* @return 值
+	**/
+	public function GetAppid()
+	{
+		return $this->values['appid'];
+	}
+	/**
+	* 判断微信分配的公众账号ID是否存在
+	* @return true 或 false
+	**/
+	public function IsAppidSet()
+	{
+		return array_key_exists('appid', $this->values);
+	}
+
+
+	/**
+	* 设置微信支付分配的商户号
+	* @param string $value 
+	**/
+	public function SetMch_id($value)
+	{
+		$this->values['mch_id'] = $value;
+	}
+	/**
+	* 获取微信支付分配的商户号的值
+	* @return 值
+	**/
+	public function GetMch_id()
+	{
+		return $this->values['mch_id'];
+	}
+	/**
+	* 判断微信支付分配的商户号是否存在
+	* @return true 或 false
+	**/
+	public function IsMch_idSet()
+	{
+		return array_key_exists('mch_id', $this->values);
+	}
+
+
+	/**
+	* 设置微信支付分配的终端设备号,商户自定义
+	* @param string $value 
+	**/
+	public function SetDevice_info($value)
+	{
+		$this->values['device_info'] = $value;
+	}
+	/**
+	* 获取微信支付分配的终端设备号,商户自定义的值
+	* @return 值
+	**/
+	public function GetDevice_info()
+	{
+		return $this->values['device_info'];
+	}
+	/**
+	* 判断微信支付分配的终端设备号,商户自定义是否存在
+	* @return true 或 false
+	**/
+	public function IsDevice_infoSet()
+	{
+		return array_key_exists('device_info', $this->values);
+	}
+
+
+	/**
+	* 设置随机字符串,不长于32位。推荐随机数生成算法
+	* @param string $value 
+	**/
+	public function SetNonce_str($value)
+	{
+		$this->values['nonce_str'] = $value;
+	}
+	/**
+	* 获取随机字符串,不长于32位。推荐随机数生成算法的值
+	* @return 值
+	**/
+	public function GetNonce_str()
+	{
+		return $this->values['nonce_str'];
+	}
+	/**
+	* 判断随机字符串,不长于32位。推荐随机数生成算法是否存在
+	* @return true 或 false
+	**/
+	public function IsNonce_strSet()
+	{
+		return array_key_exists('nonce_str', $this->values);
+	}
+
+
+	/**
+	* 设置上报对应的接口的完整URL,类似:https://api.mch.weixin.qq.com/pay/unifiedorder对于被扫支付,为更好的和商户共同分析一次业务行为的整体耗时情况,对于两种接入模式,请都在门店侧对一次被扫行为进行一次单独的整体上报,上报URL指定为:https://api.mch.weixin.qq.com/pay/micropay/total关于两种接入模式具体可参考本文档章节:被扫支付商户接入模式其它接口调用仍然按照调用一次,上报一次来进行。
+	* @param string $value 
+	**/
+	public function SetInterface_url($value)
+	{
+		$this->values['interface_url'] = $value;
+	}
+	/**
+	* 获取上报对应的接口的完整URL,类似:https://api.mch.weixin.qq.com/pay/unifiedorder对于被扫支付,为更好的和商户共同分析一次业务行为的整体耗时情况,对于两种接入模式,请都在门店侧对一次被扫行为进行一次单独的整体上报,上报URL指定为:https://api.mch.weixin.qq.com/pay/micropay/total关于两种接入模式具体可参考本文档章节:被扫支付商户接入模式其它接口调用仍然按照调用一次,上报一次来进行。的值
+	* @return 值
+	**/
+	public function GetInterface_url()
+	{
+		return $this->values['interface_url'];
+	}
+	/**
+	* 判断上报对应的接口的完整URL,类似:https://api.mch.weixin.qq.com/pay/unifiedorder对于被扫支付,为更好的和商户共同分析一次业务行为的整体耗时情况,对于两种接入模式,请都在门店侧对一次被扫行为进行一次单独的整体上报,上报URL指定为:https://api.mch.weixin.qq.com/pay/micropay/total关于两种接入模式具体可参考本文档章节:被扫支付商户接入模式其它接口调用仍然按照调用一次,上报一次来进行。是否存在
+	* @return true 或 false
+	**/
+	public function IsInterface_urlSet()
+	{
+		return array_key_exists('interface_url', $this->values);
+	}
+
+
+	/**
+	* 设置接口耗时情况,单位为毫秒
+	* @param string $value 
+	**/
+	public function SetExecute_time_($value)
+	{
+		$this->values['execute_time_'] = $value;
+	}
+	/**
+	* 获取接口耗时情况,单位为毫秒的值
+	* @return 值
+	**/
+	public function GetExecute_time_()
+	{
+		return $this->values['execute_time_'];
+	}
+	/**
+	* 判断接口耗时情况,单位为毫秒是否存在
+	* @return true 或 false
+	**/
+	public function IsExecute_time_Set()
+	{
+		return array_key_exists('execute_time_', $this->values);
+	}
+
+
+	/**
+	* 设置SUCCESS/FAIL此字段是通信标识,非交易标识,交易是否成功需要查看trade_state来判断
+	* @param string $value 
+	**/
+	public function SetReturn_code($value)
+	{
+		$this->values['return_code'] = $value;
+	}
+	/**
+	* 获取SUCCESS/FAIL此字段是通信标识,非交易标识,交易是否成功需要查看trade_state来判断的值
+	* @return 值
+	**/
+	public function GetReturn_code()
+	{
+		return $this->values['return_code'];
+	}
+	/**
+	* 判断SUCCESS/FAIL此字段是通信标识,非交易标识,交易是否成功需要查看trade_state来判断是否存在
+	* @return true 或 false
+	**/
+	public function IsReturn_codeSet()
+	{
+		return array_key_exists('return_code', $this->values);
+	}
+
+
+	/**
+	* 设置返回信息,如非空,为错误原因签名失败参数格式校验错误
+	* @param string $value 
+	**/
+	public function SetReturn_msg($value)
+	{
+		$this->values['return_msg'] = $value;
+	}
+	/**
+	* 获取返回信息,如非空,为错误原因签名失败参数格式校验错误的值
+	* @return 值
+	**/
+	public function GetReturn_msg()
+	{
+		return $this->values['return_msg'];
+	}
+	/**
+	* 判断返回信息,如非空,为错误原因签名失败参数格式校验错误是否存在
+	* @return true 或 false
+	**/
+	public function IsReturn_msgSet()
+	{
+		return array_key_exists('return_msg', $this->values);
+	}
+
+
+	/**
+	* 设置SUCCESS/FAIL
+	* @param string $value 
+	**/
+	public function SetResult_code($value)
+	{
+		$this->values['result_code'] = $value;
+	}
+	/**
+	* 获取SUCCESS/FAIL的值
+	* @return 值
+	**/
+	public function GetResult_code()
+	{
+		return $this->values['result_code'];
+	}
+	/**
+	* 判断SUCCESS/FAIL是否存在
+	* @return true 或 false
+	**/
+	public function IsResult_codeSet()
+	{
+		return array_key_exists('result_code', $this->values);
+	}
+
+
+	/**
+	* 设置ORDERNOTEXIST—订单不存在SYSTEMERROR—系统错误
+	* @param string $value 
+	**/
+	public function SetErr_code($value)
+	{
+		$this->values['err_code'] = $value;
+	}
+	/**
+	* 获取ORDERNOTEXIST—订单不存在SYSTEMERROR—系统错误的值
+	* @return 值
+	**/
+	public function GetErr_code()
+	{
+		return $this->values['err_code'];
+	}
+	/**
+	* 判断ORDERNOTEXIST—订单不存在SYSTEMERROR—系统错误是否存在
+	* @return true 或 false
+	**/
+	public function IsErr_codeSet()
+	{
+		return array_key_exists('err_code', $this->values);
+	}
+
+
+	/**
+	* 设置结果信息描述
+	* @param string $value 
+	**/
+	public function SetErr_code_des($value)
+	{
+		$this->values['err_code_des'] = $value;
+	}
+	/**
+	* 获取结果信息描述的值
+	* @return 值
+	**/
+	public function GetErr_code_des()
+	{
+		return $this->values['err_code_des'];
+	}
+	/**
+	* 判断结果信息描述是否存在
+	* @return true 或 false
+	**/
+	public function IsErr_code_desSet()
+	{
+		return array_key_exists('err_code_des', $this->values);
+	}
+
+
+	/**
+	* 设置商户系统内部的订单号,商户可以在上报时提供相关商户订单号方便微信支付更好的提高服务质量。 
+	* @param string $value 
+	**/
+	public function SetOut_trade_no($value)
+	{
+		$this->values['out_trade_no'] = $value;
+	}
+	/**
+	* 获取商户系统内部的订单号,商户可以在上报时提供相关商户订单号方便微信支付更好的提高服务质量。 的值
+	* @return 值
+	**/
+	public function GetOut_trade_no()
+	{
+		return $this->values['out_trade_no'];
+	}
+	/**
+	* 判断商户系统内部的订单号,商户可以在上报时提供相关商户订单号方便微信支付更好的提高服务质量。 是否存在
+	* @return true 或 false
+	**/
+	public function IsOut_trade_noSet()
+	{
+		return array_key_exists('out_trade_no', $this->values);
+	}
+
+
+	/**
+	* 设置发起接口调用时的机器IP 
+	* @param string $value 
+	**/
+	public function SetUser_ip($value)
+	{
+		$this->values['user_ip'] = $value;
+	}
+	/**
+	* 获取发起接口调用时的机器IP 的值
+	* @return 值
+	**/
+	public function GetUser_ip()
+	{
+		return $this->values['user_ip'];
+	}
+	/**
+	* 判断发起接口调用时的机器IP 是否存在
+	* @return true 或 false
+	**/
+	public function IsUser_ipSet()
+	{
+		return array_key_exists('user_ip', $this->values);
+	}
+
+
+	/**
+	* 设置系统时间,格式为yyyyMMddHHmmss,如2009年12月27日9点10分10秒表示为20091227091010。其他详见时间规则
+	* @param string $value 
+	**/
+	public function SetTime($value)
+	{
+		$this->values['time'] = $value;
+	}
+	/**
+	* 获取系统时间,格式为yyyyMMddHHmmss,如2009年12月27日9点10分10秒表示为20091227091010。其他详见时间规则的值
+	* @return 值
+	**/
+	public function GetTime()
+	{
+		return $this->values['time'];
+	}
+	/**
+	* 判断系统时间,格式为yyyyMMddHHmmss,如2009年12月27日9点10分10秒表示为20091227091010。其他详见时间规则是否存在
+	* @return true 或 false
+	**/
+	public function IsTimeSet()
+	{
+		return array_key_exists('time', $this->values);
+	}
+}
+
+/**
+ * 
+ * 短链转换输入对象
+ * @author widyhu
+ *
+ */
+class WxPayShortUrl extends WxPayDataBase
+{
+	/**
+	* 设置微信分配的公众账号ID
+	* @param string $value 
+	**/
+	public function SetAppid($value)
+	{
+		$this->values['appid'] = $value;
+	}
+	/**
+	* 获取微信分配的公众账号ID的值
+	* @return 值
+	**/
+	public function GetAppid()
+	{
+		return $this->values['appid'];
+	}
+	/**
+	* 判断微信分配的公众账号ID是否存在
+	* @return true 或 false
+	**/
+	public function IsAppidSet()
+	{
+		return array_key_exists('appid', $this->values);
+	}
+
+
+	/**
+	* 设置微信支付分配的商户号
+	* @param string $value 
+	**/
+	public function SetMch_id($value)
+	{
+		$this->values['mch_id'] = $value;
+	}
+	/**
+	* 获取微信支付分配的商户号的值
+	* @return 值
+	**/
+	public function GetMch_id()
+	{
+		return $this->values['mch_id'];
+	}
+	/**
+	* 判断微信支付分配的商户号是否存在
+	* @return true 或 false
+	**/
+	public function IsMch_idSet()
+	{
+		return array_key_exists('mch_id', $this->values);
+	}
+
+
+	/**
+	* 设置需要转换的URL,签名用原串,传输需URL encode
+	* @param string $value 
+	**/
+	public function SetLong_url($value)
+	{
+		$this->values['long_url'] = $value;
+	}
+	/**
+	* 获取需要转换的URL,签名用原串,传输需URL encode的值
+	* @return 值
+	**/
+	public function GetLong_url()
+	{
+		return $this->values['long_url'];
+	}
+	/**
+	* 判断需要转换的URL,签名用原串,传输需URL encode是否存在
+	* @return true 或 false
+	**/
+	public function IsLong_urlSet()
+	{
+		return array_key_exists('long_url', $this->values);
+	}
+
+
+	/**
+	* 设置随机字符串,不长于32位。推荐随机数生成算法
+	* @param string $value 
+	**/
+	public function SetNonce_str($value)
+	{
+		$this->values['nonce_str'] = $value;
+	}
+	/**
+	* 获取随机字符串,不长于32位。推荐随机数生成算法的值
+	* @return 值
+	**/
+	public function GetNonce_str()
+	{
+		return $this->values['nonce_str'];
+	}
+	/**
+	* 判断随机字符串,不长于32位。推荐随机数生成算法是否存在
+	* @return true 或 false
+	**/
+	public function IsNonce_strSet()
+	{
+		return array_key_exists('nonce_str', $this->values);
+	}
+}
+
+/**
+ * 
+ * 提交被扫输入对象
+ * @author widyhu
+ *
+ */
+class WxPayMicroPay extends WxPayDataBase
+{
+	/**
+	* 设置微信分配的公众账号ID
+	* @param string $value 
+	**/
+	public function SetAppid($value)
+	{
+		$this->values['appid'] = $value;
+	}
+	/**
+	* 获取微信分配的公众账号ID的值
+	* @return 值
+	**/
+	public function GetAppid()
+	{
+		return $this->values['appid'];
+	}
+	/**
+	* 判断微信分配的公众账号ID是否存在
+	* @return true 或 false
+	**/
+	public function IsAppidSet()
+	{
+		return array_key_exists('appid', $this->values);
+	}
+
+
+	/**
+	* 设置微信支付分配的商户号
+	* @param string $value 
+	**/
+	public function SetMch_id($value)
+	{
+		$this->values['mch_id'] = $value;
+	}
+	/**
+	* 获取微信支付分配的商户号的值
+	* @return 值
+	**/
+	public function GetMch_id()
+	{
+		return $this->values['mch_id'];
+	}
+	/**
+	* 判断微信支付分配的商户号是否存在
+	* @return true 或 false
+	**/
+	public function IsMch_idSet()
+	{
+		return array_key_exists('mch_id', $this->values);
+	}
+
+
+	/**
+	* 设置终端设备号(商户自定义,如门店编号)
+	* @param string $value 
+	**/
+	public function SetDevice_info($value)
+	{
+		$this->values['device_info'] = $value;
+	}
+	/**
+	* 获取终端设备号(商户自定义,如门店编号)的值
+	* @return 值
+	**/
+	public function GetDevice_info()
+	{
+		return $this->values['device_info'];
+	}
+	/**
+	* 判断终端设备号(商户自定义,如门店编号)是否存在
+	* @return true 或 false
+	**/
+	public function IsDevice_infoSet()
+	{
+		return array_key_exists('device_info', $this->values);
+	}
+
+
+	/**
+	* 设置随机字符串,不长于32位。推荐随机数生成算法
+	* @param string $value 
+	**/
+	public function SetNonce_str($value)
+	{
+		$this->values['nonce_str'] = $value;
+	}
+	/**
+	* 获取随机字符串,不长于32位。推荐随机数生成算法的值
+	* @return 值
+	**/
+	public function GetNonce_str()
+	{
+		return $this->values['nonce_str'];
+	}
+	/**
+	* 判断随机字符串,不长于32位。推荐随机数生成算法是否存在
+	* @return true 或 false
+	**/
+	public function IsNonce_strSet()
+	{
+		return array_key_exists('nonce_str', $this->values);
+	}
+
+	/**
+	* 设置商品或支付单简要描述
+	* @param string $value 
+	**/
+	public function SetBody($value)
+	{
+		$this->values['body'] = $value;
+	}
+	/**
+	* 获取商品或支付单简要描述的值
+	* @return 值
+	**/
+	public function GetBody()
+	{
+		return $this->values['body'];
+	}
+	/**
+	* 判断商品或支付单简要描述是否存在
+	* @return true 或 false
+	**/
+	public function IsBodySet()
+	{
+		return array_key_exists('body', $this->values);
+	}
+
+
+	/**
+	* 设置商品名称明细列表
+	* @param string $value 
+	**/
+	public function SetDetail($value)
+	{
+		$this->values['detail'] = $value;
+	}
+	/**
+	* 获取商品名称明细列表的值
+	* @return 值
+	**/
+	public function GetDetail()
+	{
+		return $this->values['detail'];
+	}
+	/**
+	* 判断商品名称明细列表是否存在
+	* @return true 或 false
+	**/
+	public function IsDetailSet()
+	{
+		return array_key_exists('detail', $this->values);
+	}
+
+
+	/**
+	* 设置附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据
+	* @param string $value 
+	**/
+	public function SetAttach($value)
+	{
+		$this->values['attach'] = $value;
+	}
+	/**
+	* 获取附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据的值
+	* @return 值
+	**/
+	public function GetAttach()
+	{
+		return $this->values['attach'];
+	}
+	/**
+	* 判断附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据是否存在
+	* @return true 或 false
+	**/
+	public function IsAttachSet()
+	{
+		return array_key_exists('attach', $this->values);
+	}
+
+
+	/**
+	* 设置商户系统内部的订单号,32个字符内、可包含字母, 其他说明见商户订单号
+	* @param string $value 
+	**/
+	public function SetOut_trade_no($value)
+	{
+		$this->values['out_trade_no'] = $value;
+	}
+	/**
+	* 获取商户系统内部的订单号,32个字符内、可包含字母, 其他说明见商户订单号的值
+	* @return 值
+	**/
+	public function GetOut_trade_no()
+	{
+		return $this->values['out_trade_no'];
+	}
+	/**
+	* 判断商户系统内部的订单号,32个字符内、可包含字母, 其他说明见商户订单号是否存在
+	* @return true 或 false
+	**/
+	public function IsOut_trade_noSet()
+	{
+		return array_key_exists('out_trade_no', $this->values);
+	}
+
+
+	/**
+	* 设置订单总金额,单位为分,只能为整数,详见支付金额
+	* @param string $value 
+	**/
+	public function SetTotal_fee($value)
+	{
+		$this->values['total_fee'] = $value;
+	}
+	/**
+	* 获取订单总金额,单位为分,只能为整数,详见支付金额的值
+	* @return 值
+	**/
+	public function GetTotal_fee()
+	{
+		return $this->values['total_fee'];
+	}
+	/**
+	* 判断订单总金额,单位为分,只能为整数,详见支付金额是否存在
+	* @return true 或 false
+	**/
+	public function IsTotal_feeSet()
+	{
+		return array_key_exists('total_fee', $this->values);
+	}
+
+
+	/**
+	* 设置符合ISO 4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型
+	* @param string $value 
+	**/
+	public function SetFee_type($value)
+	{
+		$this->values['fee_type'] = $value;
+	}
+	/**
+	* 获取符合ISO 4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型的值
+	* @return 值
+	**/
+	public function GetFee_type()
+	{
+		return $this->values['fee_type'];
+	}
+	/**
+	* 判断符合ISO 4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型是否存在
+	* @return true 或 false
+	**/
+	public function IsFee_typeSet()
+	{
+		return array_key_exists('fee_type', $this->values);
+	}
+
+
+	/**
+	* 设置调用微信支付API的机器IP 
+	* @param string $value 
+	**/
+	public function SetSpbill_create_ip($value)
+	{
+		$this->values['spbill_create_ip'] = $value;
+	}
+	/**
+	* 获取调用微信支付API的机器IP 的值
+	* @return 值
+	**/
+	public function GetSpbill_create_ip()
+	{
+		return $this->values['spbill_create_ip'];
+	}
+	/**
+	* 判断调用微信支付API的机器IP 是否存在
+	* @return true 或 false
+	**/
+	public function IsSpbill_create_ipSet()
+	{
+		return array_key_exists('spbill_create_ip', $this->values);
+	}
+
+
+	/**
+	* 设置订单生成时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010。详见时间规则
+	* @param string $value 
+	**/
+	public function SetTime_start($value)
+	{
+		$this->values['time_start'] = $value;
+	}
+	/**
+	* 获取订单生成时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010。详见时间规则的值
+	* @return 值
+	**/
+	public function GetTime_start()
+	{
+		return $this->values['time_start'];
+	}
+	/**
+	* 判断订单生成时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010。详见时间规则是否存在
+	* @return true 或 false
+	**/
+	public function IsTime_startSet()
+	{
+		return array_key_exists('time_start', $this->values);
+	}
+
+
+	/**
+	* 设置订单失效时间,格式为yyyyMMddHHmmss,如2009年12月27日9点10分10秒表示为20091227091010。详见时间规则
+	* @param string $value 
+	**/
+	public function SetTime_expire($value)
+	{
+		$this->values['time_expire'] = $value;
+	}
+	/**
+	* 获取订单失效时间,格式为yyyyMMddHHmmss,如2009年12月27日9点10分10秒表示为20091227091010。详见时间规则的值
+	* @return 值
+	**/
+	public function GetTime_expire()
+	{
+		return $this->values['time_expire'];
+	}
+	/**
+	* 判断订单失效时间,格式为yyyyMMddHHmmss,如2009年12月27日9点10分10秒表示为20091227091010。详见时间规则是否存在
+	* @return true 或 false
+	**/
+	public function IsTime_expireSet()
+	{
+		return array_key_exists('time_expire', $this->values);
+	}
+
+
+	/**
+	* 设置商品标记,代金券或立减优惠功能的参数,说明详见代金券或立减优惠
+	* @param string $value 
+	**/
+	public function SetGoods_tag($value)
+	{
+		$this->values['goods_tag'] = $value;
+	}
+	/**
+	* 获取商品标记,代金券或立减优惠功能的参数,说明详见代金券或立减优惠的值
+	* @return 值
+	**/
+	public function GetGoods_tag()
+	{
+		return $this->values['goods_tag'];
+	}
+	/**
+	* 判断商品标记,代金券或立减优惠功能的参数,说明详见代金券或立减优惠是否存在
+	* @return true 或 false
+	**/
+	public function IsGoods_tagSet()
+	{
+		return array_key_exists('goods_tag', $this->values);
+	}
+
+
+	/**
+	* 设置扫码支付授权码,设备读取用户微信中的条码或者二维码信息
+	* @param string $value 
+	**/
+	public function SetAuth_code($value)
+	{
+		$this->values['auth_code'] = $value;
+	}
+	/**
+	* 获取扫码支付授权码,设备读取用户微信中的条码或者二维码信息的值
+	* @return 值
+	**/
+	public function GetAuth_code()
+	{
+		return $this->values['auth_code'];
+	}
+	/**
+	* 判断扫码支付授权码,设备读取用户微信中的条码或者二维码信息是否存在
+	* @return true 或 false
+	**/
+	public function IsAuth_codeSet()
+	{
+		return array_key_exists('auth_code', $this->values);
+	}
+}
+
+/**
+ * 
+ * 撤销输入对象
+ * @author widyhu
+ *
+ */
+class WxPayReverse extends WxPayDataBase
+{
+	/**
+	* 设置微信分配的公众账号ID
+	* @param string $value 
+	**/
+	public function SetAppid($value)
+	{
+		$this->values['appid'] = $value;
+	}
+	/**
+	* 获取微信分配的公众账号ID的值
+	* @return 值
+	**/
+	public function GetAppid()
+	{
+		return $this->values['appid'];
+	}
+	/**
+	* 判断微信分配的公众账号ID是否存在
+	* @return true 或 false
+	**/
+	public function IsAppidSet()
+	{
+		return array_key_exists('appid', $this->values);
+	}
+
+
+	/**
+	* 设置微信支付分配的商户号
+	* @param string $value 
+	**/
+	public function SetMch_id($value)
+	{
+		$this->values['mch_id'] = $value;
+	}
+	/**
+	* 获取微信支付分配的商户号的值
+	* @return 值
+	**/
+	public function GetMch_id()
+	{
+		return $this->values['mch_id'];
+	}
+	/**
+	* 判断微信支付分配的商户号是否存在
+	* @return true 或 false
+	**/
+	public function IsMch_idSet()
+	{
+		return array_key_exists('mch_id', $this->values);
+	}
+
+
+	/**
+	* 设置微信的订单号,优先使用
+	* @param string $value 
+	**/
+	public function SetTransaction_id($value)
+	{
+		$this->values['transaction_id'] = $value;
+	}
+	/**
+	* 获取微信的订单号,优先使用的值
+	* @return 值
+	**/
+	public function GetTransaction_id()
+	{
+		return $this->values['transaction_id'];
+	}
+	/**
+	* 判断微信的订单号,优先使用是否存在
+	* @return true 或 false
+	**/
+	public function IsTransaction_idSet()
+	{
+		return array_key_exists('transaction_id', $this->values);
+	}
+
+
+	/**
+	* 设置商户系统内部的订单号,transaction_id、out_trade_no二选一,如果同时存在优先级:transaction_id> out_trade_no
+	* @param string $value 
+	**/
+	public function SetOut_trade_no($value)
+	{
+		$this->values['out_trade_no'] = $value;
+	}
+	/**
+	* 获取商户系统内部的订单号,transaction_id、out_trade_no二选一,如果同时存在优先级:transaction_id> out_trade_no的值
+	* @return 值
+	**/
+	public function GetOut_trade_no()
+	{
+		return $this->values['out_trade_no'];
+	}
+	/**
+	* 判断商户系统内部的订单号,transaction_id、out_trade_no二选一,如果同时存在优先级:transaction_id> out_trade_no是否存在
+	* @return true 或 false
+	**/
+	public function IsOut_trade_noSet()
+	{
+		return array_key_exists('out_trade_no', $this->values);
+	}
+
+
+	/**
+	* 设置随机字符串,不长于32位。推荐随机数生成算法
+	* @param string $value 
+	**/
+	public function SetNonce_str($value)
+	{
+		$this->values['nonce_str'] = $value;
+	}
+	/**
+	* 获取随机字符串,不长于32位。推荐随机数生成算法的值
+	* @return 值
+	**/
+	public function GetNonce_str()
+	{
+		return $this->values['nonce_str'];
+	}
+	/**
+	* 判断随机字符串,不长于32位。推荐随机数生成算法是否存在
+	* @return true 或 false
+	**/
+	public function IsNonce_strSet()
+	{
+		return array_key_exists('nonce_str', $this->values);
+	}
+}
+
+/**
+ * 
+ * 提交JSAPI输入对象
+ * @author widyhu
+ *
+ */
+class WxPayJsApiPay extends WxPayDataBase
+{
+	/**
+	* 设置微信分配的公众账号ID
+	* @param string $value 
+	**/
+	public function SetAppid($value)
+	{
+		$this->values['appId'] = $value;
+	}
+	/**
+	* 获取微信分配的公众账号ID的值
+	* @return 值
+	**/
+	public function GetAppid()
+	{
+		return $this->values['appId'];
+	}
+	/**
+	* 判断微信分配的公众账号ID是否存在
+	* @return true 或 false
+	**/
+	public function IsAppidSet()
+	{
+		return array_key_exists('appId', $this->values);
+	}
+
+
+	/**
+	* 设置支付时间戳
+	* @param string $value 
+	**/
+	public function SetTimeStamp($value)
+	{
+		$this->values['timeStamp'] = $value;
+	}
+	/**
+	* 获取支付时间戳的值
+	* @return 值
+	**/
+	public function GetTimeStamp()
+	{
+		return $this->values['timeStamp'];
+	}
+	/**
+	* 判断支付时间戳是否存在
+	* @return true 或 false
+	**/
+	public function IsTimeStampSet()
+	{
+		return array_key_exists('timeStamp', $this->values);
+	}
+	
+	/**
+	* 随机字符串
+	* @param string $value 
+	**/
+	public function SetNonceStr($value)
+	{
+		$this->values['nonceStr'] = $value;
+	}
+	/**
+	* 获取notify随机字符串值
+	* @return 值
+	**/
+	public function GetReturn_code()
+	{
+		return $this->values['nonceStr'];
+	}
+	/**
+	* 判断随机字符串是否存在
+	* @return true 或 false
+	**/
+	public function IsReturn_codeSet()
+	{
+		return array_key_exists('nonceStr', $this->values);
+	}
+
+
+	/**
+	* 设置订单详情扩展字符串
+	* @param string $value 
+	**/
+	public function SetPackage($value)
+	{
+		$this->values['package'] = $value;
+	}
+	/**
+	* 获取订单详情扩展字符串的值
+	* @return 值
+	**/
+	public function GetPackage()
+	{
+		return $this->values['package'];
+	}
+	/**
+	* 判断订单详情扩展字符串是否存在
+	* @return true 或 false
+	**/
+	public function IsPackageSet()
+	{
+		return array_key_exists('package', $this->values);
+	}
+	
+	/**
+	* 设置签名方式
+	* @param string $value 
+	**/
+	public function SetSignType($value)
+	{
+		$this->values['signType'] = $value;
+	}
+	/**
+	* 获取签名方式
+	* @return 值
+	**/
+	public function GetSignType()
+	{
+		return $this->values['signType'];
+	}
+	/**
+	* 判断签名方式是否存在
+	* @return true 或 false
+	**/
+	public function IsSignTypeSet()
+	{
+		return array_key_exists('signType', $this->values);
+	}
+	
+	/**
+	* 设置签名方式
+	* @param string $value 
+	**/
+	public function SetPaySign($value)
+	{
+		$this->values['paySign'] = $value;
+	}
+	/**
+	* 获取签名方式
+	* @return 值
+	**/
+	public function GetPaySign()
+	{
+		return $this->values['paySign'];
+	}
+	/**
+	* 判断签名方式是否存在
+	* @return true 或 false
+	**/
+	public function IsPaySignSet()
+	{
+		return array_key_exists('paySign', $this->values);
+	}
+}
+
+/**
+ * 
+ * 扫码支付模式一生成二维码参数
+ * @author widyhu
+ *
+ */
+class WxPayBizPayUrl extends WxPayDataBase
+{
+		/**
+	* 设置微信分配的公众账号ID
+	* @param string $value 
+	**/
+	public function SetAppid($value)
+	{
+		$this->values['appid'] = $value;
+	}
+	/**
+	* 获取微信分配的公众账号ID的值
+	* @return 值
+	**/
+	public function GetAppid()
+	{
+		return $this->values['appid'];
+	}
+	/**
+	* 判断微信分配的公众账号ID是否存在
+	* @return true 或 false
+	**/
+	public function IsAppidSet()
+	{
+		return array_key_exists('appid', $this->values);
+	}
+
+
+	/**
+	* 设置微信支付分配的商户号
+	* @param string $value 
+	**/
+	public function SetMch_id($value)
+	{
+		$this->values['mch_id'] = $value;
+	}
+	/**
+	* 获取微信支付分配的商户号的值
+	* @return 值
+	**/
+	public function GetMch_id()
+	{
+		return $this->values['mch_id'];
+	}
+	/**
+	* 判断微信支付分配的商户号是否存在
+	* @return true 或 false
+	**/
+	public function IsMch_idSet()
+	{
+		return array_key_exists('mch_id', $this->values);
+	}
+	
+	/**
+	* 设置支付时间戳
+	* @param string $value 
+	**/
+	public function SetTime_stamp($value)
+	{
+		$this->values['time_stamp'] = $value;
+	}
+	/**
+	* 获取支付时间戳的值
+	* @return 值
+	**/
+	public function GetTime_stamp()
+	{
+		return $this->values['time_stamp'];
+	}
+	/**
+	* 判断支付时间戳是否存在
+	* @return true 或 false
+	**/
+	public function IsTime_stampSet()
+	{
+		return array_key_exists('time_stamp', $this->values);
+	}
+	
+	/**
+	* 设置随机字符串
+	* @param string $value 
+	**/
+	public function SetNonce_str($value)
+	{
+		$this->values['nonce_str'] = $value;
+	}
+	/**
+	* 获取随机字符串的值
+	* @return 值
+	**/
+	public function GetNonce_str()
+	{
+		return $this->values['nonce_str'];
+	}
+	/**
+	* 判断随机字符串是否存在
+	* @return true 或 false
+	**/
+	public function IsNonce_strSet()
+	{
+		return array_key_exists('nonce_str', $this->values);
+	}
+	
+	/**
+	* 设置商品ID
+	* @param string $value 
+	**/
+	public function SetProduct_id($value)
+	{
+		$this->values['product_id'] = $value;
+	}
+	/**
+	* 获取商品ID的值
+	* @return 值
+	**/
+	public function GetProduct_id()
+	{
+		return $this->values['product_id'];
+	}
+	/**
+	* 判断商品ID是否存在
+	* @return true 或 false
+	**/
+	public function IsProduct_idSet()
+	{
+		return array_key_exists('product_id', $this->values);
+	}
+}

+ 13 - 0
extend/wxpay/lib/WxPay.Exception.php

@@ -0,0 +1,13 @@
+<?php
+/**
+ * 
+ * 微信支付API异常类
+ * @author widyhu
+ *
+ */
+class WxPayException extends Exception {
+	public function errorMessage()
+	{
+		return $this->getMessage();
+	}
+}

+ 85 - 0
extend/wxpay/lib/WxPay.Notify.php

@@ -0,0 +1,85 @@
+<?php
+/**
+ * 
+ * 回调基础类
+ * @author widyhu
+ *
+ */
+class WxPayNotify extends WxPayNotifyReply
+{
+	/**
+	 * 
+	 * 回调入口
+	 * @param bool $needSign  是否需要签名输出
+	 */
+	final public function Handle($needSign = true)
+	{
+		$msg = "OK";
+		//当返回false的时候,表示notify中调用NotifyCallBack回调失败获取签名校验失败,此时直接回复失败
+		$result = WxpayApi::notify(array($this, 'NotifyCallBack'), $msg);
+		if($result == false){
+			$this->SetReturn_code("FAIL");
+			$this->SetReturn_msg($msg);
+			$this->ReplyNotify(false);
+			return;
+		} else {
+			//该分支在成功回调到NotifyCallBack方法,处理完成之后流程
+			$this->SetReturn_code("SUCCESS");
+			$this->SetReturn_msg("OK");
+		}
+		$this->ReplyNotify($needSign);
+	}
+	
+	/**
+	 * 
+	 * 回调方法入口,子类可重写该方法
+	 * 注意:
+	 * 1、微信回调超时时间为2s,建议用户使用异步处理流程,确认成功之后立刻回复微信服务器
+	 * 2、微信服务器在调用失败或者接到回包为非确认包的时候,会发起重试,需确保你的回调是可以重入
+	 * @param array $data 回调解释出的参数
+	 * @param string $msg 如果回调处理失败,可以将错误信息输出到该方法
+	 * @return true回调出来完成不需要继续回调,false回调处理未完成需要继续回调
+	 */
+	public function NotifyProcess($data, &$msg)
+	{
+		//TODO 用户基础该类之后需要重写该方法,成功的时候返回true,失败返回false
+		return true;
+	}
+	
+	/**
+	 * 
+	 * notify回调方法,该方法中需要赋值需要输出的参数,不可重写
+	 * @param array $data
+	 * @return true回调出来完成不需要继续回调,false回调处理未完成需要继续回调
+	 */
+	final public function NotifyCallBack($data)
+	{
+		$msg = "OK";
+		$result = $this->NotifyProcess($data, $msg);
+		
+		if($result == true){
+			$this->SetReturn_code("SUCCESS");
+			$this->SetReturn_msg("OK");
+		} else {
+			$this->SetReturn_code("FAIL");
+			$this->SetReturn_msg($msg);
+		}
+		return $result;
+	}
+	
+	/**
+	 * 
+	 * 回复通知
+	 * @param bool $needSign 是否需要签名输出
+	 */
+	final private function ReplyNotify($needSign = true)
+	{
+		//如果需要签名
+		if($needSign == true && 
+			$this->GetReturn_code($return_code) == "SUCCESS")
+		{
+			$this->SetSign();
+		}
+		WxpayApi::replyNotify($this->ToXml());
+	}
+}

+ 10 - 0
extend/wxpay/qrcode.php

@@ -0,0 +1,10 @@
+<?php
+/**
+ * 生成支付二维码
+ */
+error_reporting(E_ERROR);
+require_once 'example/phpqrcode/phpqrcode.php';
+$data = $_GET["data"];
+$size = $_GET["size"]?$_GET["size"]:6;
+$margin = $_GET["margin"]?$_GET["margin"]:1;
+QRcode::png($data,false,QR_ECLEVEL_L,$size,$margin);