zoukankan      html  css  js  c++  java
  • 微信内置浏览器支付

    前端页面

    //验证是否是微信内置浏览器
            function is_weixn(){
                var ua = navigator.userAgent.toLowerCase();
                if(ua.match(/MicroMessenger/i) == "micromessenger"){
                    return true;
                } else {
                    return false;
                }
            }

    PHP

                case '3':             //微信内置浏览器JSAPI支付
                    $sHtml = '<form id="orderSubmit" name="orderSubmit" action="'.U('Wechat/wxpayJsApi').'" method="post">';
                    $sHtml .= '<input type="hidden" name="out_trade_no" value="'.$order['order_sn'].'" />';
                    $sHtml .= '<input type="hidden" name="body" value="萄萄汇商城 - '.$goods_name.'" />';
                    $sHtml .= '<input type="hidden" name="total_fee" value="'.$order['payable_amount'].'" />';
                    $sHtml .= '<input type="submit" value="Submit" style="display:none;" /></form>';
                    $sHtml .= '<script>document.forms["orderSubmit"].submit();</script>';
                    echo $sHtml;
                    break;

    DEOM

    <?php
    namespace MobileController;
    use ThinkController;
    class WechatController extends Controller{
        //$stime = microtime(true);
        //$etime = microtime(true); echo ($etime - $stime);
        //需先设置好微信支付授权目录和网页授权域名,扫码支付模式一需设置支付回调URL,模式二不需要设置
        const TOKEN = 'StupidLi';    //token令牌
        //const ORIGINAL_ID = 'gh_63e349ac0af5';    //微信公众号原始ID
        const APP_ID = 'wx8d7d0d6d81dc5056';    //微信公众号应用ID
        const APP_SECRET = 'cc41f16e6620443dcb7a4f6e85efbbca';    //微信公众号应用密钥
        //const ENCODING_AES_KEY = 'S1X0CAP7JlNInE6NKyglXdZWt2rrh0g1oIIpOOil3rH';    //消息加解密密钥
        const MCH_ID = '1420243602';    //微信支付商户号
        const MCH_KEY = '0MrxTO6bhOikziaGnAMgr1xec9bIFRxP';    //微信支付商户密钥
        const RETURN_URL = 'http://m.tthwine.com/Wechat/wxpayReturn.html';    //支付结果同步通知地址
        const NOTIFY_URL = 'http://m.tthwine.com/Wechat/wxpayNotify.html';    //支付结果异步通知地址
        /**
         * TODO:设置商户证书路径
         * 证书路径,注意应该填写绝对路径(仅退款、撤销订单时需要,可登录商户平台下载,
         * API证书下载地址:https://pay.weixin.qq.com/index.php/account/api_cert,下载之前需要安装商户操作证书)
         */
        const SSLCERT_PATH = './ThinkPHP/Library/Vendor/Wechat/cert/apiclient_cert.pem';
        const SSLKEY_PATH = './ThinkPHP/Library/Vendor/Wechat/cert/apiclient_key.pem';
        /**
         * TODO:这里设置CURL代理机器,只有需要代理的时候才设置,不需要代理,请设置为0.0.0.0和0
         * 本例程通过curl使用HTTP POST方法,此处可修改代理服务器,
         * 默认CURL_PROXY_HOST=0.0.0.0和CURL_PROXY_PORT=0,此时不开启代理(如有需要才设置)
         */
        const CURL_PROXY_HOST = '0.0.0.0';          //"10.152.18.220"
        const CURL_PROXY_PORT = 0;                  //8080
    
        private $access_token = '';      //公共基础开发的access_token
        private $access_token_a = '';    //用户授权凭证,即用code换取的access_token,
        private $curl_timeout = 30;      //curl超时
    
        public function _initialize(){
            header("Content-type: text/html; charset=utf-8");
            vendor("Wechat.WxPayException");    //异常处理类
            vendor("Wechat.WxPayFunction");    //基础方法类
        }
    
        //微信应用基础开发服务地址
        public function index(){
            //file_put_contents('./Data/paylog/wechatlog.txt', $_SERVER['REMOTE_ADDR'].'   '.$_SERVER['QUERY_STRING']."
    ", FILE_APPEND);
            if(isset($_GET['echostr'])){    //验证token
                $checkResult = $this->checkSignature($_GET['signature'], TOKEN, $_GET['timestamp'], $_GET['nonce']);
                if($checkResult == true){
                    echo $_GET['echostr'];
                    exit;
                }
            }else{
                $this->reponseMsg();
                //其他基础开发程序
                //libxml_disable_entity_loader(true);
                //$values = json_decode(json_encode(simplexml_load_string($res, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
                //file_put_contents("./Data/paylog/TEXTQ.txt", "1111333", FILE_APPEND );
            }
        }
        //应用开发验证签名
        protected function checkSignature($signature, $token, $timestamp, $nonce){
            $tmpArr = array($token, $timestamp, $nonce);
            sort($tmpArr, SORT_STRING);
            $tmpStr = implode($tmpArr);
            $tmpStr = sha1($tmpStr);
            if($tmpStr == $signature){
                return true;
            }else{
                return false;
            }
        }
        //回复事件
        public function reponseMsg(){
            //1.获取到微信推送过来post数据(xml格式)
            $postArr = $GLOBALS['HTTP_RAW_POST_DATA'];
            //2.处理消息类型,并设置回复类型和内容
            $postObj = simplexml_load_string( $postArr );
            //判断该数据包是否是订阅的事件推送
            if( strtolower( $postObj->MsgType) == 'event'){
                //如果是关注 subscribe 事件
                if( strtolower($postObj->Event == 'subscribe') ){
                    //回复用户消息(纯文本格式)
                    $toUser   = $postObj->FromUserName;
                    $fromUser = $postObj->ToUserName;
                    $arr = array(
                    array(
                        'title'=>'中秋月醇-月饼礼盒套装可预定啦',
                        'description'=>"中秋月醇-十二星座红酒配月饼礼盒套装可以预定了",
                        'picUrl'=>'https://mmbiz.qlogo.cn/mmbiz_jpg/gOCpHN587Z330josics98BkbFntIeVHq795A4ibqicANzzicdOico79kqOaHHicdMeFD9CwyKhk1BYTw4sS7icuTg0V1g/0?wx_fmt=jpeg',
                        'url'=>'https://mp.weixin.qq.com/s?__biz=MzIzMTY5MzI3Ng==&mid=2247483661&idx=1&sn=7e51c19aa3ec2672986c4b35d07e74b1&chksm=e8a10fbedfd686a8cd571951b64abcf2f680e6bdcbfdf4fb764dae22a961d9c91b78e471b5a3#rd',
                    ),
                    array(
                        'title'=>'百葡汇--名庄红酒价格搜索中心',
                        'description'=>"百葡汇--名庄红酒价格搜索中心",
                        'picUrl'=>'http://www.baipuhui.com/Public/Home/Images/logo.png',
                        'url'=>'http://www.baipuhui.com/',
                    ),
                    array(
                        'title'=>'萄萄汇--红酒商城',
                        'description'=>"葡葡汇--红酒商城",
                        'picUrl'=>'http://www.tthwine.com/Public/Home/img/logo.png',
                        'url'=>'http://m.tthwine.com',
                    ),
                );
                $template = "<xml>
                            <ToUserName><![CDATA[%s]]></ToUserName>
                            <FromUserName><![CDATA[%s]]></FromUserName>
                            <CreateTime>%s</CreateTime>
                            <MsgType><![CDATA[%s]]></MsgType>
                            <ArticleCount>".count($arr)."</ArticleCount>
                            <Articles>";
                foreach($arr as $k=>$v){
                    $template .="<item>
                                <Title><![CDATA[".$v['title']."]]></Title>
                                <Description><![CDATA[".$v['description']."]]></Description>
                                <PicUrl><![CDATA[".$v['picUrl']."]]></PicUrl>
                                <Url><![CDATA[".$v['url']."]]></Url>
                                </item>";
                }
    
                $template .="</Articles>
                            </xml> ";
                echo sprintf($template, $toUser, $fromUser, time(), 'news');
                }elseif( strtolower($postObj->Event == 'unsubscribe') ){
                    //回复用户消息(纯文本格式)
                    $toUser   = $postObj->FromUserName;
                    $fromUser = $postObj->ToUserName;
                    $time     = time();
                    $msgType  =  'event';
                    $event    =     'unsubscribe';
                    $content  = '欢迎关注我们的微信公众账号';
                    $template = "<xml>
                                <ToUserName><![CDATA[%s]]></ToUserName>
                                <FromUserName><![CDATA[%s]]></FromUserName>
                                <CreateTime>%s</CreateTime>
                                <MsgType><![CDATA[%s]]></MsgType>
                                <Event><![CDATA[%s]]></Event>
                                </xml>";
                    $info     = sprintf($toUser, $fromUser, $time, $msgType, $event, $content, $template);
                    echo $info;
                }
    
            }
    
            //内容的回复多图文的
            if( strtolower($postObj->MsgType) == 'text' && strtolower($postObj->Content)=='tw' ){
                $toUser = $postObj->FromUserName;
                $fromUser = $postObj->ToUserName;
                $arr = array(
                    array(
                        'title'=>'再见科比,再见青春',
                        'description'=>"再见科比,再见青春",
                        'picUrl'=>'http://img1.gtimg.com/sports/pics/hv1/226/138/2052/133466716.jpg',
                        'url'=>'http://sports.qq.com/a/20160414/040599.htm',
                    ),
                    array(
                        'title'=>'百葡汇--红酒搜索中心',
                        'description'=>"百葡汇--红酒搜索中心",
                        'picUrl'=>'http://www.baipuhui.com/Public/Home/Images/logo.png',
                        'url'=>'http://www.baipuhui.com/',
                    ),
                    array(
                        'title'=>'淘淘wine',
                        'description'=>"淘淘wine",
                        'picUrl'=>'http://www.tthwine.com/Public/Home/img/logo.png',
                        'url'=>'http://www.tthwine.com/',
                    ),
                );
                $template = "<xml>
                            <ToUserName><![CDATA[%s]]></ToUserName>
                            <FromUserName><![CDATA[%s]]></FromUserName>
                            <CreateTime>%s</CreateTime>
                            <MsgType><![CDATA[%s]]></MsgType>
                            <ArticleCount>".count($arr)."</ArticleCount>
                            <Articles>";
                foreach($arr as $k=>$v){
                    $template .="<item>
                                <Title><![CDATA[".$v['title']."]]></Title>
                                <Description><![CDATA[".$v['description']."]]></Description>
                                <PicUrl><![CDATA[".$v['picUrl']."]]></PicUrl>
                                <Url><![CDATA[".$v['url']."]]></Url>
                                </item>";
                }
    
                $template .="</Articles>
                            </xml> ";
                echo sprintf($template, $toUser, $fromUser, time(), 'news');
    
                //注意:进行多图文发送时,子图文个数不能超过10个
            }else{
                switch( strtolower($postObj->Content) ){
                    case 1:
                        $content = '您输入的数字是1';
                    break;
                    case 2:
                        $content = '您输入的数字是2';
                    break;
                    case 3:
                        $content = '您输入的数字是3';
                    break;
                    case 4:
                        $content = "<a href='http://www.imooc.com'>慕课</a>";
                    break;
                    case '英文':
                        $content = 'imooc is ok';
                    break;
                }
                    $template = "<xml>
                            <ToUserName><![CDATA[%s]]></ToUserName>
                            <FromUserName><![CDATA[%s]]></FromUserName>
                            <CreateTime>%s</CreateTime>
                            <MsgType><![CDATA[%s]]></MsgType>
                            <Content><![CDATA[%s]]></Content>
                            </xml>";
                //注意模板中的中括号 不能少 也不能多
                    $fromUser = $postObj->ToUserName;
                    $toUser   = $postObj->FromUserName;
                    $time     = time();
                    $msgType  = 'text';
                    echo sprintf($template, $toUser, $fromUser, $time, $msgType, $content);
    
            }//if end
            // 付款推送
            if( strtolower( $postObj->MsgType) == 'event'){
                if( strtolower( $postObj->Event) == 'merchant_order'){
                        $toUser   = $postObj->FromUserName;
                        $fromUser = $postObj->ToUserName;
                        $time     = time();
                        $msgType  = 'event';
                        $event    = 'merchant_order';
                        $OrderId  = $postObj->OrderId;
                        $OrderStatus = '2';
                        $ProductId = $postObj->ProductId;
                        $SkuInfo  = $postObj->SkuInfo;
                        $template = "<xml>
                                    <ToUserName><![CDATA[%s]]></ToUserName>
                                    <FromUserName><![CDATA[%s]]></FromUserName>
                                    <CreateTime>%s</CreateTime>
                                    <MsgType><![CDATA[%s]]></MsgType>
                                    <Event><![CDATA[%s]]></Event>
                                    <OrderId><![CDATA[%s]]></OrderId>
                                    <OrderStatus>%s</OrderStatus>
                                    <ProductId><![CDATA[%s]]></ProductId>
                                    <SkuInfo><![CDATA[%s]]></SkuInfo>
                                    </xml>";
                        echo sprintf($template, $toUser, $fromUser, $time, $msgType, $event, $OrderId, $OrderStatus, $ProductId, $SkuInfo);
                }
            }
            return $postArr;
        }//reponseMsg 括号
        //获取AccessToken
        public function getWxAccessToken(){
            //1.请求url地址
            $appid = 'wx8d7d0d6d81dc5056';
            $appsecret =  'cc41f16e6620443dcb7a4f6e85efbbca';
            if (time()-S('expires_in')<7000) {
                    $access_token = S('access_token');
                    //var_dump($access_token);
                      return $access_token;
                }else{
                    $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" . $appid . "&secret=" . $appsecret . "";
                    $data = webCurl($url);
                    $arr = json_decode($data,true);
                    S('access_token',$arr['access_token'],7000);
                    $access_token = S('access_token');
                    $data = array(
                        "access_token" => $access_token,
                        "expires_in"=> time(),
                    );
                    S('expires_in',$data['expires_in'],7000);
                    //var_dump($access_token);
                    //$_SESSION['access_token_expires_in'] = $data['expires_in'];
                    return $data['access_token'];
                }
        }
        //自定义菜单栏
        public function setmenu()
        {
            $access_token = $this->getWxAccessToken();
            $url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=".$access_token;
            $data = array(
                'button'=>array(
                    array(
                        "name"=>"微信商城",
                           "sub_button"=>array(
                               array(
                                   "type"=>"view",
                                "name"=>"中秋月醇",
                                "url"=>"http://m.tthwine.com/Goods/index/W_category/376.html"
                                   ),
                               array(
                                   "type"=>"view",
                                "name"=>"生肖套装",
                                "url"=>"http://m.tthwine.com/Goods/detail/id/413.html"
                                   ),
                               array(
                                   "type"=>"view",
                                "name"=>"萄萄汇商城",
                                "url"=>"http://m.tthwine.com/"
                                   ),
                               array(
                                   "type"=>"view",
                                "name"=>"特价优惠",
                                "url"=>"http://m.tthwine.com/Goods/index.html"
                                   ),
    
                               )
                        ),
                    array(
                        "name"=>"名庄报价",
                           "sub_button"=>array(
                               array(
                                   "type"=>"view",
                                "name"=>"价格查询",
                                "url"=>"http://m.baipuhui.com/"
                                   ),
                               array(
                                   "type"=>"view",
                                "name"=>"供应商报价",
                                "url"=>"http://m.baipuhui.com/ProductPrice/indexs.html"
                                   ),
                               array(
                                   "type"=>"view",
                                "name"=>"全球货源",
                                "url"=>"http://m.baipuhui.com/BusinessList/index.html"
                                   ),
    
                               )
                        ),
                    array(
                        "name"=>"用户中心",
                           "sub_button"=>array(
                               // array(
                               //     "type"=>"view",
                               //  "name"=>"小店订单",
                               //  "url"=>"http://mp.weixin.qq.com/bizmall/mallshelf?id=&t=mall/list&biz=MzIzMTY5MzI3Ng==&shelf_id=2&showwxpaytitle=1#wechat_redirect"
                               //     ),
                               array(
                                   "type"=>"view",
                                "name"=>"商城订单",
                                "url"=>"http://m.tthwine.com/Member/order.html"
                                   ),
                               array(
                                    "type"=>"view",
                                "name"=>"物流跟踪",
                                 "url"=>"https://m.kuaidi100.com/index.jsp"
                                    ),
                               array(
                                   "type"=>"view",
                                "name"=>"个人中心",
                                "url"=>"http://m.tthwine.com/Member/index.html"
                                   ),
    
                               )
                        ),
                    ),
                );
            $data = webCurl($url,1,json_encode($data,JSON_UNESCAPED_UNICODE));
        }
        //登录获取用户信息
        public function login()
        {
            $appid = 'wx8d7d0d6d81dc5056';
            $redirect_uri = "http://m.tthwine.com/index.php/Wechat/weixinreturn";
            $redirect_uri = urlencode($redirect_uri);
            $url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=".$appid."&redirect_uri=".$redirect_uri."&response_type=code&scope=snsapi_userinfo&state=1&connect_redirect=1#wechat_redirect";
            header('Location: ' . $url . '');
        }
        public function weixinreturn()
        {
            $appid = 'wx8d7d0d6d81dc5056';
            $SECRET =  'cc41f16e6620443dcb7a4f6e85efbbca';
            $code = $_GET['code'];
            $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" .$appid. "&secret=" .$SECRET. "&code=". $code ."&grant_type=authorization_code";
            $data = json_decode(wcurl($url),true);
            $_SESSION['access_token'] = $data['access_token'];
            $_SESSION['openid'] = $data['openid'];
            $url = "https://api.weixin.qq.com/sns/userinfo?access_token=".$_SESSION['access_token']."&openid=".$_SESSION['openid']."&lang=zh_CN";
            $user = json_decode(wcurl($url),true);
            $this->assign('user',$user);
            $this->display();
            return $user;
        }
    
        //微信小店下单信息
        public function order(){
            $obj = $this-> gOrderAll($data = array());
                foreach ($obj['order_list'] as $key => $value) {
                $sql = " SELECT order_id FROM oph_wxshop WHERE order_id = '{$value['order_id']}' ";
                $res = M('wxshop')->query($sql);
                if ($res[0]['order_id'] == $value['order_id'] ) {
                     unset($value);
                 }else{
                     M('wxshop')->add($value);
                 }
            }
            $get['type']= $_GET['type'] ? $_GET['type'] : 0 ;
            switch ($get['type']){
                case 0:
                    $where = '';
                    break;
                case 1:
                    $where = ' AND order_status = 1 ';
                    break;
                case 2:
                    $where = ' AND order_status = 2 ';
                    break;
                case 3:
                    $where = ' AND order_status = 3 ';
                    break;
                case 4:
                    $where = ' AND order_status = 4 ';
                    break;
                default:
                    break;
            }
            $orderlist = M('wxshop')->query(" SELECT * FROM oph_wxshop WHERE buyer_openid = '{$_SESSION['openid']}' $where");
            $this->assign('orderlist',$orderlist);
            $this->assign('get',$get);
            $this->display();
        }
    
        //微信小店的订单详情
        public function orderinfo(){
            $oid = $_GET['order_id'] ? $_GET['order_id'] : $this->error("非法访问");
            $info = M('wxshop')->query(" SELECT * FROM oph_wxshop WHERE order_id = '{$oid}' ");
            $this->assign('info', $info);
            $this->display();
        }
    
        //获取微信订单信息
        public function gOrderAll($data = array()){
          $access_token = $this->getWxAccessToken();
          $url = "https://api.weixin.qq.com/merchant/order/getbyfilter?access_token=".$access_token;
          if(!empty($data)){
            $data = json_encode($data);
          }
          else{
            $firstday = strtotime(date("Y-m-01",time()));
            $data = array('begintime' => $firstday,'endtime' => strtotime("$firstday +1 month -1 day"));
            $data = json_encode($data);
          }
          $ResData = $this->cUrlRequest($url,$data);
          $obj = objarray_to_array(json_decode($ResData));
            return $obj;
        }
    
        public function cUrlRequest($url,$data = null){
          $curl = curl_init();
          curl_setopt($curl, CURLOPT_URL, $url);
          curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
          curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
          if (!empty($data)){
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
          }
          curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
          $output = curl_exec($curl);
          curl_close($curl);
          return $output;
        }
    
        //微信订单确认
        public function returnInfo(){
            if($_GET['oid']){
                M()->execute("UPDATE oph_wxshop SET order_status = 4 WHERE  order_id = '{$_GET['oid']}'");
            }
            $orderlist = M('wxshop')->query(" SELECT * FROM oph_wxshop WHERE buyer_openid = '{$_SESSION['openid']}' AND order_status = 4");
            $this->assign('orderlist',$orderlist);
            $this->display('wechat/order');
        }
        //微信小店发货
        public function sLogisticsList(){
                $this->Logistics['Fsearch_code'] = "邮政EMS";
                $this->Logistics['002shentong'] = "申通快递";
                $this->Logistics['066zhongtong'] = "中通速递";
                $this->Logistics['056yuantong'] = "圆通速递";
                $this->Logistics['042tiantian'] = "天天快递";
                $this->Logistics['003shunfeng'] = "顺丰速运";
                $this->Logistics['059Yunda'] = "韵达快运";
                $this->Logistics['064zhaijisong'] = "宅急送";
                $this->Logistics['020huitong'] = "汇通快运";
                $this->Logistics['zj001yixun'] = "易迅快递";
    
        }
        //发货设置
        public function sOrderDelivery($data = array("need_delivery" => '0')){
          $access_token = $this->getWxAccessToken();
          $url = "https://api.weixin.qq.com/merchant/order/setdelivery?access_token=".$access_token;
          if(!empty($data)){
            $data = json_encode($data);
          }
          else{
            $data = array("need_delivery" => '0');
            $data = json_encode($data);
          }
          $ResData = $this->cUrlRequest($url,$data);
          print_r( json_decode($ResData) );
        }
        //发货订单
        public function send()
        {
            $data['need_delivery'] = '1';
            $data['order_id'] = '13880016931595576467';
            $data['delivery_company'] = '003shunfeng';
            $data['delivery_track_no'] = '5185457726';
            $data['is_others']         = '0';
            $this->sOrderDelivery($data);
        }
    
        //获取订单详情
        // public function gOrderInfo($order){
        //         $access_token = $this->getWxAccessToken();
        //         $url = "https://api.weixin.qq.com/merchant/order/getbyid?access_token=".$access_token;
        //         $ResData = $this->cUrlRequest($url,'{"order_id": "'.$order.'"}');
        //         return(objarray_to_array(json_decode($ResData)) );
        // }
    
        //模板消息发送
        public function sendtpl_msg(){
            if (is_weixin() == false) {
                echo "<p style='font-size:32px;color:red;text-align:center'>请用微信浏览器打开</p>";
                exit;
            }
            $access_token = $this->getWxAccessToken();
            $getOpenid = $this->getOpenid();
            //$postArr = $this->reponseMsg();
            //$res = $this->gOrderInfo($postArr['OrderId']);
            //模板消息
            $template=array(
                'touser'=>$getOpenid,
                'template_id'=>"t2j4tatkUhqCvsTVr290P04rXNWg3WnMWXOHiLW6tSg",
                'url'=>"http://m.tthwine.com/index.php/Wechat/login/",
                'topcolor'=>"#7B68EE",
                'data'=>array(
                'first' => array(
                        'value' => '尊敬的用户,您好,欢迎购买我们的产品',
                        'color' => '#FF0000'
                    ),
                    'keyword1' => array(
                        'value' => $data['order_no'],
                        'color' => '#000'
                    ),
                    'keyword2' => array(
                        'value' => $data['pay_amount'].元,
                        'color' => '#000000'
                    ),
                    'remark' => array(
                        'value' => '广州欧葡汇祝您节日快乐!',
                        'color' => '#FF0000'
                    )
                )
            );
            $json_template=json_encode($template);
            $url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=".$access_token;
            $res = http_request($url,urldecode($json_template));
        }
        /**
         * 以post方式提交xml到对应的接口url
         * @param string $xml  需要post的xml数据
         * @param string $url  url
         * @param bool $useCert   是否需要证书,默认不需要
         * @param int $second   url执行超时时间,默认30s
         * @throws WxPayException
         */
        protected static function curlPostXml($xml, $url, $useCert = false, $second = 30){
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_TIMEOUT, $second);    //设置超时
            if(self::CURL_PROXY_HOST != "0.0.0.0" && self::CURL_PROXY_PORT != 0){    //如果有配置代理这里就设置代理
                curl_setopt($ch, CURLOPT_PROXY, self::CURL_PROXY_HOST);
                curl_setopt($ch, CURLOPT_PROXYPORT, self::CURL_PROXY_PORT);
            }
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); //严格校验2
            curl_setopt($ch, CURLOPT_HEADER, FALSE);    //设置header
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);   //要求结果为字符串且输出到屏幕上
            if($useCert == true){     //设置证书,使用证书:cert 与 key 分别属于两个.pem文件
                curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM');
                curl_setopt($ch, CURLOPT_SSLCERT, self::SSLCERT_PATH);
                curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM');
                curl_setopt($ch, CURLOPT_SSLKEY, self::SSLKEY_PATH);
            }
            curl_setopt($ch, CURLOPT_POST, TRUE);    //post提交方式
            curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
            $result = curl_exec($ch);    //运行curl
            if($result){    //返回结果
                curl_close($ch);
                return $result;
            }else{
                $error = curl_errno($ch);
                curl_close($ch);
                throw new WxPayException("curl出错,错误码:".$error);
            }
        }
        /**
         * 通过跳转获取用户的openid,跳转流程如下:
         * 1、设置自己需要调回的url及其其他参数,跳转到微信服务器https://open.weixin.qq.com/connect/oauth2/authorize
         * 2、微信服务处理完成之后会跳转回用户redirect_uri地址,此时会带上一些参数,如:code
         * 3、通过code请求微信服务器https://api.weixin.qq.com/sns/oauth2/access_token获取openid和access_token用户授权凭证
         * @param string $state  自定义参数
         * @return 用户的openid
         */
        protected function getOpenid($state=''){
            $tools = new WxPayFunction();
            if(!isset($_GET['code'])){    //触发微信返回code码
                $redirectUrl = urlencode('http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'].$_SERVER['QUERY_STRING']);
                $urlObj = array(
                    'appid'         => self::APP_ID,
                    'redirect_uri'  => $redirectUrl,
                    'response_type' => 'code',
                    'scope'         => 'snsapi_base',
                    'state'         => $state.'#wechat_redirect'
                );
                $bizString = $tools->ToUrlStr($urlObj);
                $url = 'https://open.weixin.qq.com/connect/oauth2/authorize?'.$bizString;
                header('Location:'.$url); exit();
            }else{    //获取code码,以获取openid
                $urlObj = array(
                    'appid'      => self::APP_ID,
                    'secret'     => self::APP_SECRET,
                    'code'       => $_GET['code'],
                    'grant_type' => 'authorization_code'
                );
                $bizString = $tools->ToUrlStr($urlObj);
                $url = 'https://api.weixin.qq.com/sns/oauth2/access_token?'.$bizString;
                $ch = curl_init();    //初始化curl
                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(self::CURL_PROXY_HOST != '0.0.0.0' && self::CURL_PROXY_PORT != 0){
                    curl_setopt($ch,CURLOPT_PROXY, self::CURL_PROXY_HOST);
                    curl_setopt($ch,CURLOPT_PROXYPORT, self::CURL_PROXY_PORT);
                }
                $result = curl_exec($ch);    //运行curl,结果以json形式返回
                curl_close($ch);
                $data = json_decode($result, true);
                $this->access_token_a = $data['access_token'];   //赋值access_token_a属性,此access_token为用户授权凭证,与基础开发的access_token不同
                return $data['openid'];    //返回openid
            }
        }
        /**
         * 统一下单,unifiedOrder中out_trade_no、body、total_fee、trade_type必填
         * appid、mchid、spbill_create_ip、nonce_str不需要填入
         * @param WxPayUnifiedOrder $inputObj
         * @param int $timeOut
         * @throws WxPayException 抛出异常
         * @return array 成功时返回结果
         */
        protected function unifiedOrder($requestArr, $timeOut = 10){
            //检测参数
            if(!array_key_exists('out_trade_no', $requestArr)){
                throw new WxPayException("缺少统一支付接口必填参数out_trade_no!");
            }else if(!array_key_exists('body', $requestArr)){
                throw new WxPayException("缺少统一支付接口必填参数body!");
            }else if(!array_key_exists('total_fee', $requestArr)){
                throw new WxPayException("缺少统一支付接口必填参数total_fee!");
            }else if(!array_key_exists('trade_type', $requestArr)){
                throw new WxPayException("缺少统一支付接口必填参数trade_type!");
            }
            //关联参数
            if($requestArr['trade_type'] == "JSAPI" && !array_key_exists('openid', $requestArr)){
                throw new WxPayException("统一支付接口中,缺少必填参数openid!trade_type为JSAPI时,openid为必填参数!");
            }
            if($requestArr['trade_type'] == "NATIVE" && !array_key_exists('product_id', $requestArr)){
                throw new WxPayException("统一支付接口中,缺少必填参数product_id!trade_type为JSAPI时,product_id为必填参数!");
            }
            $tools = new WxPayFunction();
            $url= 'https://api.mch.weixin.qq.com/pay/unifiedorder';    //统一下单API请求地址
            $requestArr['appid'] = self::APP_ID;    //String(32) 应用ID
            $requestArr['mch_id'] = self::MCH_ID;    //String(32) 商户ID
            $requestArr['nonce_str'] = $tools->createNonceStr(32);    //String(32) 随机字符串
            $requestArr['spbill_create_ip'] = $_SERVER['REMOTE_ADDR'];    //String(16) 终端IP
            $requestArr['notify_url'] = self::NOTIFY_URL;    //String(256) 异步通知地址
            $requestArr['sign'] = $tools->createSign($requestArr, self::MCH_KEY);    //String(32) 签名
    
            $requestXml = $tools->arrToXml($requestArr);
            $responseXml = self::curlPostXml($requestXml, $url, false, $timeOut);
            $responseArr = $tools->xmlToArr($responseXml);
            return $responseArr;
        }
        /**
         * 获取jsApi的json参数
         * @param string $prepay_id 预支付交易标识
         * @return jsApi前端json参数
         */
        protected function getJsApiParameters($prepay_id){
            $tools = new WxPayFunction();
            $jsApiArr = array(
                'appId'     => self::APP_ID,                                            //String(16) 应用ID
                'timeStamp' => strval(time()),                                          //String(32) 时间戳
                'nonceStr'  => $tools->createNonceStr(32),                              //String(32) 随机字符串
                'package'   => 'prepay_id='.$prepay_id,                                 //String(128) 订单详情扩展字符串
                'signType'  => 'MD5'                                                    //String(32) 签名方式
            );
            $jsApiArr['paySign'] = $tools->createSign($jsApiArr, self::MCH_KEY);        //String(64) 签名
            return json_encode($jsApiArr);
        }
        /**
         * 获取共享地址json参数
         * @param string $access_token  用户授权凭证
         * @return 共享地址前段json参数
         */
        protected function getEditAddrParameters($access_token){
            $tools = new WxPayFunction();
            $addrSignArr = array(
                'appid'       => self::APP_ID,                                               //String(16) 应用ID
                'url'         => 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'],    //当前网页URL
                'timestamp'   => strval(time()),                                             //String(32) 时间戳
                'noncestr'    => $tools->createNonceStr(32),                                 //String(32) 随机字符串
                'accesstoken' => $access_token                                               //String(256) 用户授权凭证
            );
            ksort($addrSignArr);
            $addrSignStr = $tools->toUrlStr($addrSignArr);
            $addrSign = sha1($addrSignStr);
            $editAddrArr = array(
                'appId'     => self::APP_ID,                             //String(16) 应用ID
                'scope'     => 'jsapi_address',                          //String(32) 编辑地址权限
                'signType'  => 'sha1',                                   //String(32) 签名方式
                'addrSign'  => $addrSign,                                //String(40) 签名
                'timeStamp' => $addrSignArr['timestamp'],                //String(32) 时间戳
                'nonceStr'  => $addrSignArr['noncestr']                  //String(32) 随机字符串
            );
            return json_encode($editAddrArr);
        }
        //微信支付外部浏览器H5页面MWEB支付接口(微信内测阶段,还未对外开放)
        public function wxpayH5Api(){
            $requestArr = array(
                'body'             => $_POST['body'],                                //String(128) 商品描述
                'out_trade_no'     => $_POST['out_trade_no'],                        //String(32) 商户订单号
                'total_fee'        => intval(floatval($_POST['total_fee'])*100),     //Int 订单金额(单位为分)
                'trade_type'       => 'MWEB'                                         //String(16) 交易类型
            );
            $responseArr = $this->unifiedOrder($requestArr);    //统一下单API
            $tools = new WxPayFunction();
            if($responseArr['return_code'] == 'SUCCESS'){    //判断返回是否成功
                if(array_key_exists('sign', $responseArr) && $tools->createSign($responseArr, self::MCH_KEY) == $responseArr['sign']){
                    header('Location:'.$responseArr['mweb_url'].'&redirect_url='.urlencode(self::RETURN_URL));    //跳转启动微信APP支付
                }else{
                    throw new WxPayException("签名验证失败!");
                }
            }else{        //$responseArr['return_code'] == 'FAIL'
                //记录日志$responseArr;打印出错参数
                //file_put_contents('./Data/paylog/wechatlog.txt', $_SERVER['REMOTE_ADDR'].'   '.$_SERVER['QUERY_STRING']."
    ", FILE_APPEND);
                throw new WxPayException("响应失败!");
                foreach($responseArr as $key => $val){
                    echo $key.': '.$val.'<br />';
                }
            }
        }
        //微信支付内置浏览器H5页面JSAPI支付接口
        public function wxpayJsApi(){
            //获取openId需跳转,所以将post参数存入获取openid的自定义参数中
            if(!empty($_POST['body']) && !empty($_POST['out_trade_no']) && !empty($_POST['total_fee'])){
                $state = json_encode($_POST);
            }
            //解析获取openid返回的自定义参数,从而获取最初的订单信息
            if(!empty($_GET['state'])){
                $orderData = json_decode($_GET['state'], true);
            }
            $openid = $this->getOpenid($state);    //获取openid
            $requestArr = array(
                'body'             => $orderData['body'],                               //String(128) 商品描述
                'out_trade_no'     => $orderData['out_trade_no'],                       //String(32) 商户订单号
                'total_fee'        => intval(floatval($orderData['total_fee'])*100),    //Int 订单金额(单位为分)
                'trade_type'       => 'JSAPI',                                          //String(16) 交易类型
                'openid'           => $openid                                            //String(128) trade_type=JSAPI时(即公众号支付),此参数必传,此参数为微信用户在商户对应appid下的唯一标识
            );
            $responseArr = $this->unifiedOrder($requestArr);   //统一下单API
            if(!array_key_exists('appid', $responseArr) || !array_key_exists('prepay_id', $responseArr) || $responseArr['prepay_id'] == ""){
                throw new WxPayException("参数错误!");
            }
            //获取调用jsApi的参数(json格式输出)
            $jsApiParameters = $this->getJsApiParameters($responseArr['prepay_id']);
            //获取共享收货地址的参数(json格式输出)(由于支付场景不适合,暂不使用)
            //$editAddrParameters = $this->getEditAddrParameters($this->access_token_a);
            //传递给同步通知页面的信息
            $returnData = array(
                // 'out_trade_no' => $orderData['body'],
                'out_trade_no' => $orderData['out_trade_no'],
                'total_fee'    => $orderData['total_fee'],
                'return_url'   => self::RETURN_URL
            );
            $this->assign('jsApiParameters', $jsApiParameters);
            //$this->assign('editAddrParameters', $editAddrParameters);
            $this->assign('returnData', $returnData);
            $this->display('Order/wxpay_js');
        }
        //微信支付原生支付接口(采用模式二扫码支付)
        public function wxpayNativeApi(){
            $requestArr = array(
                'body'             => $_POST['body'],                               //String(128) 商品描述
                'out_trade_no'     => $_POST['out_trade_no'],                       //String(32) 商户订单号
                'total_fee'        => intval(floatval($_POST['total_fee'])*100),    //Int 订单金额(单位为分)
                'trade_type'       => 'NATIVE',                                     //String(16) 交易类型
                'product_id'       => $_POST['out_trade_no']                        //String(32) 商品标识,商户自定义
            );
            $responseArr = $this->unifiedOrder($requestArr);    //统一下单API
            $tools = new WxPayFunction();
            if($responseArr['return_code'] == 'SUCCESS'){    //判断返回是否成功
                if(array_key_exists('sign', $responseArr) && $tools->createSign($responseArr, self::MCH_KEY) == $responseArr['sign']){    //验证签名
                    $returnData = array(      //获取订单信息和扫码支付地址
                        'out_trade_no' => $_POST['out_trade_no'],
                        'total_fee'    => $_POST['total_fee'],
                        'code_url'     => $responseArr['code_url']
                    );
                }else{
                    throw new WxPayException("签名验证失败!");
                }
            }else{       //$responseArr['return_code'] == 'FAIL'
                throw new WxPayException("响应失败!");
                foreach($responseArr as $key => $val){
                    echo $key.': '.$val.'<br />';
                }
            }
    
            $this->assign('returnData', $returnData);
            $this->display('Order/wxpay_native');
        }
        //微信支付同步通知
        public function wxpayReturn(){
            $payResult = array(
                'order_no'   => htmlspecialchars($_GET['out_trade_no']),
                'status'     => $_GET['status'],
                'pay_type'   => '微信支付',
                'pay_amount' => $_GET['total_fee']
            );
            if($payResult['status'] == 'success'){    //支付完成
                M('order')->where('`order_sn`="'.$payResult['order_no'].'" AND `pay_status`=0')->setField('pay_status', 1);
                $crowd = M('order')->alias('o')->where('(o.`is_crowd`<>0 OR o.`is_cab`<>0) AND o.`order_sn`="'.$payResult['order_no'].'"')->join('`oph_order_goods` AS og ON og.`order_id`=o.`id`','left')->join('`oph_crowd` AS c ON (c.`id`=o.`is_crowd` OR c.`id`=o.`is_cab`)','left')->field('og.`goods_id`,og.`number`,og.`box`,o.`id` oid,o.`is_crowd`,o.`is_cab`,c.*')->find();
                // var_dump($crowd);exit;
                if(!$_COOKIE[$payResult['order_no']]){
                    setcookie($payResult['order_no'],1);
                    if ($crowd) {
                        $upNum['nownum'] = $crowd['nownum'] + $crowd['number'];
                        $myCrowd = array();
                        M()->startTrans();
                        if ($crowd['is_crowd']) {
                            $res = M('crowd')->where('id='.$crowd['is_crowd'])->setField($upNum);
                            $myCrowd['cid'] = $crowd['is_crowd'];
                        }else{
                            $res = M('crowd')->where('id='.$crowd['is_cab'])->setField($upNum);
                            $myCrowd['cid'] = $crowd['is_cab'];
                        }
                        $myCrowd['myprice'] = $payResult['pay_amount'];
                        $myCrowd['uid'] = $_SESSION['user']['uid'];
                        $myCrowd['mobile'] = $_SESSION['user']['mobile'];
                        $myCrowd['num'] = $crowd['number'];
                        $order['total'] = $myCrowd['num'];
                        $myCrowd['create_time'] = time();
                        $myCrowd['oid'] = $crowd['oid'];
                        if ($res) {
                            M('crowd_join')->add($myCrowd);
                            M()->commit();
                        }else{
                            M()->rollback();
                        }
                    }
                    $order['total'] = M('order')->alias('o')->where('o.`order_sn`="'.$payResult['order_no'].'" AND og.`goods_id`<>0')->join('oph_order_goods AS og ON og.`order_id`=o.`id`')->sum('number');
                    $jiage = $payResult['pay_amount'];
                    D('member')->upLevel($jiage,$order['total']);
                }
                $payResult['msg'] = '付款完成!我们将第一时间安排发货!';
                    //发送模板消息
                    $access_token = $this->getWxAccessToken();
                    $getOpenid = $this->getOpenid();
                    //模板消息
                    $template=array(
                        'touser'=>$getOpenid,
                        'template_id'=>"t2j4tatkUhqCvsTVr290P04rXNWg3WnMWXOHiLW6tSg",
                        'url'=>"http://m.tthwine.com/Member/order",
                        'topcolor'=>"#7B68EE",
                        'data'=>array(
                        'first' => array(
                                'value' => '尊敬的用户,您好,欢迎购买我们的产品',
                                'color' => '#FF0000'
                            ),
                            'keyword1' => array(
                                'value' => $payResult['pay_amount'].元,
                                'color' => '#000'
                            ),
                            'keyword2' => array(
                                'value' => $payResult['order_no'],
                                'color' => '#000000'
                            ),
                            'remark' => array(
                                'value' => '广州十二星祝您节日快乐!',
                                'color' => '#FF0000'
                            )
                        )
                    );
                    $json_template=json_encode($template);
                    $url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=".$access_token;
                    http_request($url,urldecode($json_template));
    
    
            }else if($payResult['status'] == 'failure'){    //支付失败或出错
                $payResult['msg'] = '支付失败,请到我的订单重新发起支付!';
            }
    
            $this->assign('payResult', $payResult);   //print_r($payResult);
            $this->display('Order/result');
        }
        //微信支付异步通知
        public function wxpayNotify(){
            $notifyXml = $GLOBALS['HTTP_RAW_POST_DATA'];     //获取返回的xml数据
            $tools = new WxPayFunction();
            $notifyArr = $tools->xmlToArr($notifyXml);
            if($notifyArr['return_code'] == 'SUCCESS'){    //判断通知成功
                if($notifyArr['result_code'] == 'SUCCESS' && $tools->createSign($notifyArr, self::MCH_KEY) == $notifyArr['sign']){    //支付成功和验证签名
                    $pay_status = M('order')->where('`order_sn`="'.$notifyArr['out_trade_no'].'"')->getField('pay_status');
                    if(self::MCH_ID == $notifyArr['mch_id'] && $pay_status != 1){
                        $data = array(
                            'pay_type'       => 3,
                            'pay_status'     => 1,
                            'payreal_amount' => floatval($notifyArr['total_fee']/100),    //单位为分,换算成元
                            'pay_sn'         => $notifyArr['transaction_id'],
                            'pay_time'       => strtotime($notifyArr['time_end'])
                        );
                        $result = M('order')->where('order_sn="'.$notifyArr['out_trade_no'].'"')->save($data);
                    }
                }
                //写入日志文件(订单编号,微信交易号,交易状态,交易金额,微信用户openId,付款时间)
                file_put_contents('./Data/paylog/wxpaylog.txt', $notifyArr['out_trade_no'].'    '.$data['pay_sn'].'    '.$notifyArr['result_code'].'    '.$data['payreal_amount'].'    '.$notifyArr['openid'].'    '.$data['pay_time'].'    微信支付'."
    ", FILE_APPEND);
                $responseXml = $tools->arrToXml(array('return_code'=>'SUCCESS', 'return_msg'=>'OK'));
                echo $responseXml;
            }else{
                return false;
            }
        }
    
        //分享接口
        public function sharOne(){
            //获取商品id
            $shopId = I('get.sid');
            $getgm = I('get.gm');
            $jsapi_ticket = $this->getJsApiTicket();
            $timestamp = time();
            $noncestr = $this->getRandCode();
            // 注意 URL 一定要动态获取,不能 hardcode.
            $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
            $url = "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
            $signature = "jsapi_ticket=$jsapi_ticket&noncestr=$noncestr&timestamp=$timestamp&url=$url";
            $signature = sha1( $signature );
            if($shopId > 0){
                //获取用户微信getOpenid
                $getOpenid = $this->getOpenid();
                $getOpenid = str_replace('-','',$getOpenid);
                //获取上级分享的用户openid
                if($upOpenid = I('get.u')) $this->assign('upOpenid',$upOpenid);
                $newUrl = $protocol.$_SERVER[HTTP_HOST].'/Wechat/sharOne/u/'.$getOpenid.'/sid/'.$shopId.'.html';
                $this->assign('shopId',$shopId);
                $this->assign('getOpenid',$getOpenid);
                $this->assign('newUrl',$newUrl);
            }
            //获取地区三级联动
            $province = M('region_china')->where('pid=0')->getField('id,region_name');
            $showVive = 'sharOne'.$shopId;
            $this->assign('getgm',$getgm);
            $this->assign('province',$province);
            $this->assign('timestamp',$timestamp);
            $this->assign('noncestr',$noncestr);
            $this->assign('signature',$signature);
            $this->assign('sharOnesid',$shopId);
            $this->display($showVive);
        }
    
        //获取随机码
        public function getRandCode(){
            $array = array(
                'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
                'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','d','u','v','w','x','y','z',
                '0','1','2','3','4','5','6','7','8','9'
            );
            $tmpstr = '';
            $max = count($array);
            for($i =1; $i <= 16; $i++){
                $key = rand(0,$max-1);
                $tmpstr .= $array[$key];
            }
            return $tmpstr;
        }
    
        public function getJsApiTicket(){
            //如果session中保存有效的jsapi_ticket
            $access_token = $this->getWxAccessToken();
            if($_SESSION['jsapi_ticket_expire_time'] > time()){
                $jsapi_ticket = S('jsapi_ticket');
            }else{
                $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=$access_token&type=jsapi";
                $data = webCurl($url);
                $res = json_decode($data,true);
                $jsapi_ticket = $res['ticket'];
                S('jsapi_ticket',$jsapi_ticket,7000);
                $_SESSION['jsapi_ticket_expire_time'] = time()+7000;
            }
            return $jsapi_ticket;
        }
    }
    ?>
  • 相关阅读:
    Java连接数据库 #02# JDBC经典套路
    Eloquent JavaScript #03# functions
    Java笔记 #04# 类的初始化顺序补充
    Java笔记 #03# HtmlUnit爬虫
    Google's Machine Learning Crash Course #04# First Steps with TensorFlow
    IntelliJ IDEA. Debug模式
    python实用笔记,加快编程速度,lamdba,三元运算,open.
    开源项目管理平台*redmine*的架设
    MYSQL双主故障解决实例。
    LVS-DR工作原理
  • 原文地址:https://www.cnblogs.com/jierong12/p/9888294.html
Copyright © 2011-2022 走看看