1.支付,退款,回调 函数


<?php
 // 微信公众号AppId
 define("APPID", "");

 // 微信公众号AppSecret
 define("APPSECRET", "");

 // <微信支付> 公众号支付商户ID(partnerId)
 define("PARTNER", "");

 // <微信支付> 商户通加密串(partnerKey)
 define("PARTNERKEY", "");

 include('./weixinUtils/Util.php');
 class wxAppUtils{
     
     /**
      * 微信退货处理
      * 退货前提是必须支付成功
      * @param type $orderId
      * @return bool
      */
     public function wxRefund($transaction_id,$out_trade_no, $totalFee,$refund_fee) {
         $utils=new Util();
         $curl=new Curl();
         //微信退款
         $url = 'https://api.mch.weixin.qq.com/secapi/pay/refund';
         $out_refund_no = date("Ymdhis") . mt_rand(10, 99);
         
         $postData = array(
             "appid" => APPID,
             "mch_id" => PARTNER,
             "transaction_id" => $transaction_id,
             "out_trade_no" => $out_trade_no,
             "out_refund_no" =>$out_refund_no,
             "total_fee" => $totalFee,
             "refund_fee" => $refund_fee,
             "op_user_id" => PARTNER,
             "nonce_str" =>  $utils->createNoncestr(),
         );
         $postData["sign"] = $utils->paySign($postData);
         $reqPar =$utils->toXML($postData);
         $r =  $curl->postXmlCurl($url, $reqPar, 50);
         return $r;
         
         
     }
     
     
     /**
      * 统一下单
      * @param unknown $openid
      * @return boolean|string[]|unknown[]
      */
     
     public function weinXinPay($openid) {
         $utils=new Util();
         $curl=new Curl();
         $notify_url="http://www.weixin.qq.com/wxpay/pay.php";
         $serial_number = date("Ymdhis") . mt_rand(10, 99);
         // 随机字符串
         $nonceStr = $utils->createNoncestr();
         // 时间戳
         $timeStamp = strval(time());
         // 订单总额 = (金额 - 余额支付金额)
         $totalFee = 1;
         $pack = array(
             'appid' => APPID,
             'body' => "测试",
             'mch_id' => PARTNER,
             'nonce_str' => $nonceStr,
             'notify_url' => $notify_url,
             'spbill_create_ip' =>  $utils->getIps(),
             'openid' => $openid,
             'out_trade_no' => $serial_number,
             'total_fee' => $totalFee,
             'trade_type' => 'JSAPI'
         );
         
         $pack['sign'] = $utils->paySign($pack);
         $xml = $utils->toXML($pack);
         
         $ret = $curl->post('https://api.mch.weixin.qq.com/pay/unifiedorder', $xml);
         
         $postObj = json_decode(json_encode(simplexml_load_string($ret, 'SimpleXMLElement', LIBXML_NOCDATA)));
         
         if (empty($postObj->prepay_id) || $postObj->return_code == "FAIL") {
             echo '生成签名失败:' . $postObj->return_msg . ' ' . $xml.$ret;
             return false;
         } else {
             $packJs = array(
                 'appId' => APPID,
                 'timeStamp' => $timeStamp,
                 'nonceStr' => $nonceStr,
                 'package' => "prepay_id=" . $postObj->prepay_id,
                 'signType' => 'MD5'
             );
             $JsSign = $utils->paySign($packJs);
             unset($packJs['timeStamp']);
             $packJs['timestamp'] = $timeStamp;
             $packJs['paySign'] = $JsSign;
             return $packJs;
             
         }
         
     }

   
    
 

2.支付类

// 微信app支付回调页面
     public  function app_payment_notify(){
         $utils=new Util();
         $curl=new Curl();
         //解决$GLOBAL限制导致无法获取xml数据
         $this->sourceStr = file_get_contents('php://input');
         // 读取数据
         $postObj = simplexml_load_string($this->sourceStr, 'SimpleXMLElement', LIBXML_NOCDATA);
         // 数据参考 systemtest/payment_notify.xml
         if (!$postObj) {
             echo "支付回调处理失败,数据包解析失败";
         } else {
             // 对数据包进行签名验证
             $postArr = (array)$postObj;
             $sign    = $utils->AppPaySign($postArr);
             if ($sign == $postObj->sign) {
                 $this->app_order_callback($postObj);
             }
     
         }
     }
     
     /**
      * app支付回调
      * @param $postObj
      */
     public function app_order_callback($postObj) {
         $serial = $postObj->out_trade_no;
         // 微信交易单号
         $transaction_id = $postObj->transaction_id;
         if (!empty($transaction_id)) {
             
           //这里写你需要的逻辑
           echo "<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>";
         }
     }
     

   
     /**
      * 输出成功JSON消息
      */
     final public function echoSuccess($msg = 'success') {
         $this->echoMsg(0, $msg);
         exit();
     }
     
     /**
      * 输出JSON消息
      * @param mixed $code
      * @param mixed $msg
      */
     final public function echoMsg($code, $msg = '', $options = JSON_UNESCAPED_UNICODE) {
         return $this->echoJson(array(
             'ret_code' => $code,
             'ret_msg'  => $msg
         ), $options);
     }
     
     /**
      * 输出JSON
      * @param mixed $arr
      */
     final public function echoJson($arr, $options = JSON_UNESCAPED_UNICODE) {
         header('Content-Type: application/json; charset=utf-8');
         if (strpos(PHP_VERSION, '5.3') > -1) {
             // php 5.3-
             echo json_encode($arr);
         } else {
             // php 5.4+
             echo json_encode($arr, $options);
         }
         return true;
     }
     
 }
<!DOCTYPE html>
 <html>
 <head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
 <title>微信支付测试</title>
 <style type="text/css">
 body {margin:0px; background:#efefef; font-family:'微软雅黑'; -moz-appearance:none;}
 .weixinpay {height:44px; margin:14px 5px; background:#31cd00; border-radius:4px; text-align:center; font-size:16px; line-height:44px; color:#fff;}
 </style>
 </head>
 <body>
     <?php 
     include('./wxAppUtils.php');
     $wxPay =new wxAppUtils();
     $openid="oLkSDv7tdOWxBHXvj1Tuz_xa4W-I";
     $result=$wxPay->weinXinPay($openid);
     ?>
       appId:<input type="text" id="appId" value="<?php echo $result['appId'];?>"><br /> 
     timeStamp:<input type="text" id="timeStamp" value="<?php echo $result['timestamp'];?>"><br />
     nonceStr:<input type="text" id="nonceStr" value="<?php echo $result['nonceStr'];?>"><br />
     package:<input type="text" id="package" value="<?php echo $result['package'];?>"><br />
     signType:<input type="text" id="signType" value="<?php echo $result['signType'];?>"><br />
     paySign:<input type="text" id="paySign" value="<?php echo $result['paySign'];?>"><br />
     <div class="weixinpay">微信支付</div>
 </body>
 <script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
 <script>
 $(function(){
     $(".weixinpay").click(function(){
         WeixinJSBridge.invoke('getBrandWCPayRequest',{
               'appId':$("#appId").val(),
           'timeStamp':$("#timeStamp").val(),
            'nonceStr':$("#nonceStr").val(),
             'package':$("#package").val(),
            'signType':$("#signType").val(),
             'paySign':$("#paySign").val(),
    },
    function(res){
     //支付成功或失败前台判断
          if(res.err_msg=='get_brand_wcpay_request:ok'){
            alert('恭喜您,支付成功!');
          }else if(res.err_msg=='get_brand_wcpay_request:cancel') {
              alert('取消支付');
          }else{
            alert(res.err_msg);
          }
   });
 });
 });
 </script>
 </html>



 
 3退款测试类

<?php
 include('./wxAppUtils.php');
 $wxPay =new wxAppUtils();
 $out_trade_no="";     //订单号
 $wepay_serial="";     //唯一订单号
 $totalFee=1;     //订单金额
 $refund_fee=1;   //退款金额
 $result=$wxPay->wxRefund($wepay_serial, $out_trade_no, $totalFee, $refund_fee);//退款  
 if($result['errcode']==0){
     var_dump($result);
 }else{
    echo $result['errcode'];
 }


4.工具类

<?php

 include_once 'Curl.php';
 /**
  * @description Hope You Do Good But Not Evil
  * @copyright   Copyright 2014-2015 <ycchen@iwshop.cn>
  * @license     LGPL (http://www.gnu.org/licenses/lgpl.html)
  * @author      Chenyong Cai <ycchen@iwshop.cn>
  * @package     Wshop
  * @link        http://www.iwshop.cn
  */
 class Util 
 {

     private $DigCrypt;


     /**
      * getIPaddress
      * @return type
      */
     public function getIp() {
         $cIP  = getenv('REMOTE_ADDR');
         $cIP1 = getenv('HTTP_X_FORWARDED_FOR');
         $cIP2 = getenv('HTTP_CLIENT_IP');
         $cIP1 ? $cIP = $cIP1 : null;
         $cIP2 ? $cIP = $cIP2 : null;
         return $cIP;
     }

     /**
      * getIPaddress
      * @return type
      */
     public static function getIps() {
         $cIP  = getenv('REMOTE_ADDR');
         $cIP1 = getenv('HTTP_X_FORWARDED_FOR');
         $cIP2 = getenv('HTTP_CLIENT_IP');
         $cIP1 ? $cIP = $cIP1 : null;
         $cIP2 ? $cIP = $cIP2 : null;
         return $cIP;
     }

     /**
      * xssFilter
      * @todo function
      * @param type $str
      * @return type
      */
     public function xssFilter($str) {
         return addslashes($str);
     }

     public function getServerIP() {
         return gethostbyname($_SERVER["SERVER_NAME"]);
     }

     /**
      *
      * @param type $timestamp
      * @return string
      */
     public function dateTimeFormat($timestamp) {
         $timestamp = strtotime($timestamp);
         $curTime   = time();
         $space     = $curTime - $timestamp;
         //1分钟
         if ($space < 60) {
             $string = "刚刚";
             return $string;
         } elseif ($space < 3600) { //一小时前
             $string = floor($space / 60) . "分钟前";
             return $string;
         }
         $curtimeArray = getdate($curTime);
         $timeArray    = getDate($timestamp);
         if ($curtimeArray['year'] == $timeArray['year']) {
             if ($curtimeArray['yday'] == $timeArray['yday']) {
                 $format = "%H:%M";
                 $string = strftime($format, $timestamp);
                 return "今天 {$string}";
             } elseif (($curtimeArray['yday'] - 1) == $timeArray['yday']) {
                 $format = "%H:%M";
                 $string = strftime($format, $timestamp);
                 return "昨天 {$string}";
             } else {
                 $string = sprintf("%d月%d日 %02d:%02d", $timeArray['mon'], $timeArray['mday'], $timeArray['hours'], $timeArray['minutes']);
                 return $string;
             }
         }
         $string = sprintf("%d-%d-%d %d:%d", $timeArray['year'], $timeArray['mon'], $timeArray['mday'], $timeArray['hours'], $timeArray['minutes']);
         return $string;
     }

     /**
      * ip转换地址
      * @param string $ip
      * @return array
      */
     public function ipConvAddress($ip) {
         $json = file_get_contents('http://ip.taobao.com/service/getIpInfo.php?ip=' . $ip);
         $arr  = json_decode($json);
         return $arr->data;
     }

     public function digEncrypt($nums) {
         return $this->DigCrypt->en($nums);
     }

     public function digDecrypt($code) {
         return $this->DigCrypt->de($code);
     }

     /**
      * 性别eng转换
      * @param string $sex
      * @return string
      */
     public function sexConv($sex) {
         $s = array(
             'f' => '女',
             'm' => '男'
         );
         if (array_key_exists($sex, $s)) {
             return $s[$sex];
         } else {
             return '未知';
         }
     }

     /**
      * digitDefault
      * @param string $input
      * @param int $default
      * @return string
      */
     public static function digitDefault($input, $default = 0) {
         return (is_numeric($input) && $input > 0) ? intval($input) : $default;
     }

     /**
      * digitDefaultZero
      * @param string $input
      * @param int $default
      * @return int
      */
     public static function digitDefaultZero($input, $default = 0) {
         return (is_numeric($input) && $input > -1) ? intval($input) : $default;
     }

     /**
      * strDefault
      * @param string $input
      * @param string $default
      * @return string
      */
     public static function strDefault($input, $default = '') {
         return !empty($input) ? trim(addslashes($input)) : $default;
     }

     /**
      * 删除目录文件
      * @param string $dir
      * @return bool
      */
     public function delDirFiles($dir) {
         $dirs = dir($dir);
         if ($dirs && is_readable($dirs)) {
             try {
                 while ($file = $dirs->read()) {
                     $file = $dir . $file;
                     if (is_file($file)) {
                         unlink($file);
                     }
                 }
                 return true;
             } catch (Exception $ex) {
                 return false;
             }
         }
         return false;
     }

     /**
      * 数组转换XML
      * @param array $arr
      * @return string
      */
     public function toXML($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;
     }

     /**
      * 格式化参数格式化成url参数
      */
     public function ToUrlParams($arr) {
         $buff = "";
         foreach ($arr as $k => $v) {
             if ($k != "sign" && $v != "" && !is_array($v)) {
                 $buff .= $k . "=" . $v . "&";
             }
         }
         $buff = trim($buff, "&");
         return $buff;
     }

     /**
      * 生成签名
      * @param array $pack
      * @return string
      */
     public function paySign($pack) {
         ksort($pack);
         $string = $this->ToUrlParams($pack);
         $string = $string . "&key=" . PARTNERKEY;
         $string = md5($string);
         $result = strtoupper($string);
         return $result;
     }
     
     /**
      * 生成随机字符串
      * @param int $length
      * @return string
      */
     public function createNoncestr($length = 32) {
         $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
         $str   = "";
         for ($i = 0; $i < $length; $i++) {
             $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
             //$str .= $chars[ mt_rand(0, strlen($chars) - 1) ];  
         }
         return $str;
     }

     /**
      * 检查是否登陆
      * @return bool
      */
     public function isLogin() {
         if (isset($_COOKIE['uopenid']) && isset($_COOKIE['uid'])) {
             return $this->User->checkUserExt($_COOKIE['uopenid']);
         } else {
             return false;
         }
     }

     

     /**
      * 组合数组key
      * @param $array
      */
     public static function combineArrayKey($array) {
         $tmp = [];
         foreach ($array as $key => $a) {
             $tmp[] = $key;
         }
         return $tmp;
     }

     /**
      * 组合数组值
      * @param $array
      */
     public static function combineArrayValue($array) {
         $tmp = [];
         foreach ($array as $key => $a) {
             $tmp[] = $a;
         }
         return $tmp;
     }

     /**
      * 获取完整根域名
      * @return string
      */
     public static function getHOST() {
         return (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://" . $_SERVER['HTTP_HOST'];
     }

     /**
      * 获取请求完整路径
      * @return string
      */
     public static function getURI() {
         return self::getHOST() . $_SERVER['REQUEST_URI'];
     }

     /**
      * 获取根路径
      * @return string
      */
     public static function getROOT() {
         global $config;
         return self::getHOST() . $config->shoproot;
     }

     /**
      * @return bool|string
      */
     public static function getNOW() {
         return date('Y-m-d H:i:s');
     }

     /**
      * 打包商品图片地址数据
      * @param $name
      */
     public static function packProductImgURI($name) {
         global $config;
     
         if (isset($config->oss) && $config->oss['on']) {
             // 兼容oss
             return $name;
         } else {
             return Util::getHOST() . $config->productPicLink . $name;
         }
     }

     /**
      * 转换回调地址
      * @param string $url
      * @return string
      */
     public static function convURI($url) {
         $url = preg_replace("/(\?|\&)from=(timeline|singlemessage|groupmessage)&isappinstalled=0/", "", $url);
         $tmp = parse_url($url);
         parse_str($tmp[query], $t);
         if ($t[code] || $t[state]) {
             $a = array('code' => $t[code], 'state' => $t[state]);
             $s = http_build_query($a);
             $r = preg_replace("/(\?|\&)" . $s . "/", "", $url);
         } else {
             $r = $url;
         }
         return $r;
     }

     /**
      * 获取今天星期几
      */
     public function getTodayStr() {
         $weekarray = array(
             "日",
             "一",
             "二",
             "三",
             "四",
             "五",
             "六"
         );
         return $weekarray[date('w')];
     }

     /**
      * 充值订单序列号
      * @return string
      */
     public function createDepositSerial(){
         return "D_" . time() . mt_rand(100, 999);
     }

 }

5.请求类

<?php

 /**
  * Curl模型
  * @description Hope You Do Good But Not Evil
  * @copyright   Copyright 2014-2015 <ycchen@iwshop.cn>
  * @license     LGPL (http://www.gnu.org/licenses/lgpl.html)
  * @author      Chenyong Cai <ycchen@iwshop.cn>
  * @package     Wshop
  * @link        http://www.iwshop.cn
  */
 class Curl {
     /**
      * @param $url
      * @return mixed
      */
     public static function get($url) {
         $curl = curl_init();
         curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址
         curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查
         curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.97'); // 模拟用户使用的浏览器
         curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转
         curl_setopt($curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer
         curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环
         curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回
         $res = curl_exec($curl);
         curl_close($curl);
         return $res;
     }

     /**
      * @param $url
      * @param $postData
      * @param bool|false $raw
      * @return mixed
      */
     public static function post($url, $postData, $raw = false) {
         $curl = curl_init();
         curl_setopt($curl, CURLOPT_URL, $url);
         #curl_setopt($curl, CURLOPT_REFERER, 'https://mp.weixin.qq.com/');
         curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查
         curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.97'); // 模拟用户使用的浏览器
         curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转
         curl_setopt($curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer
         curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环
         curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回
         // post数据
         curl_setopt($curl, CURLOPT_POST, 1);
         
         //
         //关于微信报错media data missing的解决方案
         //php5.6及旧版本curl传文件差异
         if (phpversion() < 5.6){
             if (is_array($postData) && !$raw) {
                 $data = http_build_query($postData);
             }
             else{
                 $data = $postData;
             }
         }
         else{
             if (is_array($postData)) {
                 foreach ($postData as $key => $value){
                     //如果是上传文件,以@开头
                     if (substr($value,0,1) == '@'){
                         $data[$key] = new CURLFile(substr($value,1));
                     }
                     else{
                         $data[$key] = $value;
                     }
                 }
             }
             else{
                 $data = $postData;
             }
         }
         
         curl_setopt($curl, CURLOPT_POSTFIELDS,$data);
         $output = curl_exec($curl);
         curl_close($curl);
         return $output;
     }

     /**
      * @param type $url
      * @param type $head
      * @return type
      */
     public static function getWithHeader($url, $head = false) {
         $curl      = curl_init();
         $header[0] = "Accept: text/xml,application/xml,application/xhtml+xml,";
         $header[0] .= "text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5";
         $header[] = "Cache-Control: max-age=0";
         $header[] = "Connection: keep-alive";
         $header[] = "Keep-Alive: 300";
         $header[] = "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7";
         $header[] = "Accept-Language: en-us,en;q=0.5";
         $header[] = "Pragma: "; // browsers keep this blank.
         if ($header) {
             $header[] = $head;
         }
         curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
         curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址
         curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查
         curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.97'); // 模拟用户使用的浏览器
         curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转
         curl_setopt($curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer
         curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环
         curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回
         $res = curl_exec($curl);
         curl_close($curl);
         return $res;
     }
     
     /**
      * curl POST
      *
      * @param   string  url
      * @param   array   数据
      * @param   int     请求超时时间
      * @param   bool    HTTPS时是否进行严格认证
      * @return  string
      */


     function postXmlCurl($url,$xmldata, $second = 6) {
         // 证书验证与否
         $ch = curl_init();
         // 设置超时
         curl_setopt($ch, CURLOPT_TIMEOUT, $second);
         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);
         // 退款严格使用证书,必须是公众号所对应的商户平台下的证书才可以,安全不的外泄
         // 设置证书
         // 使用证书:cert 与 key 分别属于两个.pem文件
         curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
         curl_setopt($ch,CURLOPT_SSLCERT,"./weixinUtils/cert/apiclient_cert.pem");
         curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
         curl_setopt($ch,CURLOPT_SSLKEY,"./weixinUtils/cert/apiclient_key.pem");
         // post提交方式
         curl_setopt($ch, CURLOPT_POST, TRUE);
         curl_setopt($ch, CURLOPT_POSTFIELDS, $xmldata);
         // 运行curl
         $xml = curl_exec($ch);
         $error = curl_errno($ch);
         curl_close($ch);
       
         // 返回结果0的时候能只能表明程序是正常返回不一定说明退款成功而已
         if($xml){
             // 把xml转化成数组
             $xmlstring =simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
             $result['errcode'] = 0;
             $result['result']  =$xmlstring;
             return $result;
         }else{
             // 错误的时候返回错误码。
             $result['errcode'] = $error;
             return $result;
         }
     }  

 }

百度云下载地址


http://pan.baidu.com/s/1dET2rEL 
 密码:iot1