微信内置浏览器支付

前端页面

//验证是否是微信内置浏览器
        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 Mobile\Controller;
use Think\Controller;
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']."\r\n", 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']."\r\n", 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'].'    微信支付'."\r\n", 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;
    }
}
?>

猜你喜欢

转载自www.cnblogs.com/jierong12/p/9888294.html