zoukankan      html  css  js  c++  java
  • ThinkPHP 整合微信支付 扫码支付 模式二 图文教程

    这篇文章主要介绍扫码支付场景二。

    目前有两种模式,模式一比模式二稍微复杂点,至于模式一与模式二的具体内容,流程,微信开发文档都有详细介绍,这里就不多说废话,接下来赶紧上教程!

    [title]下载SDK类文件[/title]

    Wxpay Library

    并SDK文件/lib下的几个文件放置到//Library/Vendor/

    [title]修改WxPay.pub.config.php中的配置选项[/title]

    	//=======【基本信息设置】=====================================
    	//微信公众号身份的唯一标识。审核通过后,在微信发送的邮件中查看
    	const APPID = '公众号表示ID';
    	//受理商ID,身份标识
    	const MCHID = '商户ID';
    	//商户支付密钥Key。审核通过后,在微信发送的邮件中查看
    	const KEY = 'KEY密匙';
    	//JSAPI接口中获取openid,审核后在公众平台开启开发模式后可查看
    	const APPSECRET = 'SECRET密匙';
    	
    	//=======【JSAPI路径设置】===================================
    	//获取access_token过程中的跳转uri,通过跳转将code传入jsapi支付页面
    	const JS_API_CALL_URL = 'http://www.laoji.org';
    	
    	//=======【证书路径设置】=====================================
    	//证书路径,注意应该填写绝对路径
    	const SSLCERT_PATH =  "__ROOT__paypem\apiclient_cert.pem";
    	const SSLKEY_PATH =   "__ROOT__paypem\apiclient_key.pem";
    	
    	//=======【异步通知url设置】===================================
    	//异步通知url,商户根据实际开发过程设定
    	const NOTIFY_URL = 'http://www.laoji.org/wxpay/notify';
    
    	//=======【curl超时设置】===================================
    	//本例程通过curl使用HTTP POST方法,此处可修改其超时时间,默认为30秒
    	const CURL_TIMEOUT = 30;
    
    

    [title]新建微信的Controller方法,目录位置为:ApplicationHomeControllerWxpayController.class.php [/title]

    <?php
    /**
     * WxpayController.class.php
     * 微信支付控制器
     * 网站地址:   https://www.jiloc.com/43212.
     * Author: 老季 ( admin@laoji.org ) 
     * Date: 2017年4月18日
    */
    namespace HomeController;
    
    class WxpayController extends HomeController {
        //初始化
        public function _initialize()
        {
            //引入类文件
            vendor('Wxpay.WxPayPubHelper');
        }
        
        private function makeOrder($ary){
            $data = array();
            $data['userid'] = session('user_auth')['uid'];
            if ( !$data['userid'] ){
                $this->error('用户ID错误! -> '.$data['uid'],'/my/publishlist');
            } 
            // 检查船舶信息
            $data['shipinfoid'] = $ary['id'];
            $ShipInfo = M('ShipInfo')->where(array('id'=>$ary['id']))->find();
            if( !$ShipInfo ){
                $this->error('信息ID错误! -> '.$ary['id'],'/my/publishlist');
            }
            // 检查支付价格
            $data['ordercatid'] = $ary['catid'];
            $OrderCat = M('OrderCat')->where(array('id'=>$ary['catid']))->find();
            if( !$OrderCat ){
                $this->error('产品价格错误! -> '.$ary['catid'],'/my/publishlist');
            }
            
            $data['ordid'] = "LJ".$ary['TYPE'].date('YmdHis',time()).rand(11,99);
            $data['ordtime'] = time();
            
            $data['ordtitle'] = $ShipInfo['title'];
            $data['ordbuydays'] = $OrderCat['days'];
            $data['ordfee'] = $data['ordprice'] = $OrderCat['price'];
            $data['status'] = 0;
            
            M('OrderList')->add($data);
            
            return $data['ordid'];
            
        }
        
        //生成二维码
        public function qrcode()
        {
            // 生成订单
            $_POST['TYPE'] = 'W';
            $out_trade_no = $this->makeOrder($_POST);
            $ordtotal_fee = str_replace(".","",$_POST['ordtotal_fee']*100);
            //使用统一支付接口
            $unifiedOrder = new UnifiedOrder_pub();
            //设置统一支付接口参数
            //设置必填参数
            $unifiedOrder->setParameter("body",$_POST['ordsubject'] );//商品描述
            //自定义订单号,此处仅作举例
            $timeStamp = time();
            $unifiedOrder->setParameter("out_trade_no",$out_trade_no);//商户订单号 
            $unifiedOrder->setParameter("total_fee",$ordtotal_fee);//总金额
            $unifiedOrder->setParameter("notify_url", WxPayConf_pub::NOTIFY_URL);//通知地址 
            $unifiedOrder->setParameter("trade_type","NATIVE");//交易类型
            //非必填参数,商户可根据实际情况选填
            //$unifiedOrder->setParameter("sub_mch_id","XXXX");//子商户号  
            //$unifiedOrder->setParameter("device_info","XXXX");//设备号 
            //$unifiedOrder->setParameter("attach","XXXX");//附加数据 
            //$unifiedOrder->setParameter("time_start","XXXX");//交易起始时间
            //$unifiedOrder->setParameter("time_expire","XXXX");//交易结束时间 
    //         $unifiedOrder->setParameter("goods_tag","");//商品标记 
    //         $unifiedOrder->setParameter("openid","19405");//用户标识
            //$unifiedOrder->setParameter("product_id","XXXX");//商品ID
            //获取统一支付接口结果
            $unifiedOrderResult = $unifiedOrder->getResult();
    //         var_dump($unifiedOrder);
            //商户根据实际情况设置相应的处理流程
            if ($unifiedOrderResult["return_code"] == "FAIL") 
            {
                //商户自行增加处理流程
                echo "通信出错:".$unifiedOrderResult['return_msg']."<br>";
            }
            elseif($unifiedOrderResult["result_code"] == "FAIL")
            {
                //商户自行增加处理流程
                echo "错误代码:".$unifiedOrderResult['err_code']."<br>";
                echo "错误代码描述:".$unifiedOrderResult['err_code_des']."<br>";
            }
            elseif($unifiedOrderResult["code_url"] != NULL)
            {
                //从统一支付接口获取到code_url
                $code_url = $unifiedOrderResult["code_url"];
                //商户自行增加处理流程
                //......
            }
            $this->assign('title',$_POST['ordsubject']);
            $this->assign('total_fee',$_POST['ordtotal_fee']);
            $this->assign('out_trade_no',$out_trade_no);
            $this->assign('code_url',urlencode($code_url));
            $this->assign('unifiedOrderResult',$unifiedOrderResult);
            
            $this->display();
        }
        
        public function notify()
        {
            //使用通用通知接口
            $notify = new Notify_pub();
            //存储微信的回调
            $xml = $GLOBALS['HTTP_RAW_POST_DATA'];
            $notify->saveData($xml);
    //          var_dump($xml);
            //验证签名,并回应微信。
            //对后台通知交互时,如果微信收到商户的应答不是成功或超时,微信认为通知失败,
            //微信会通过一定的策略(如30分钟共8次)定期重新发起通知,
            //尽可能提高通知的成功率,但微信不保证通知最终能成功。
            if($notify->checkSign() == FALSE){
                $notify->setReturnParameter("return_code","FAIL");//返回状态码
                $notify->setReturnParameter("return_msg","签名失败");//返回信息
            }else{
                $notify->setReturnParameter("return_code","SUCCESS");//设置返回码
            }
            $returnXml = $notify->returnXml();
            echo $returnXml;
             
            //==商户根据实际情况设置相应的处理流程,此处仅作举例=======
             
            //以log文件形式记录回调信息
            //         $log_ = new Log_();
    //        $log_name= __ROOT__."/Public/notify_url.log";//log文件路径
             
    //        $this->log_result($log_name,"【接收到的notify通知】:
    ".$xml."
    ");
             
            if($notify->checkSign() == TRUE)
            {
                if ($notify->data["return_code"] == "FAIL") {
                    //此处应该更新一下订单状态,商户自行增删操作
                    log_result($log_name,"【通信出错】:
    ".$xml."
    ");
                    $this->error("通信出错");
                }
                elseif($notify->data["result_code"] == "FAIL"){
                    //此处应该更新一下订单状态,商户自行增删操作
    //                log_result($log_name,"【业务出错】:
    ".$xml."
    ");
                    $this->error("业务出错");
                }
                elseif( $notify->data['return_code'] == "SUCCESS" && $notify->data['result_code'] == "SUCCESS"){
                    $out_trade_no   = $notify->data['out_trade_no'];
                    $parameter = array(
                        "out_trade_no"     => $notify->data['out_trade_no'],    //商户订单编号;
                        "transaction_id"         => $notify->data['transaction_id'],  //微信支付订单号	
                        "total_fee"        => $notify->data['total_fee'],       //交易金额;
                        "result_code"     => "SUCCESS",                        //交易状态
                        "time_end"    => $notify->data['time_end'],          //支付完成时间
                        "openid"    => $notify->data['openid'],            //用户标识	
                    );
                    if (!$this->checkorderstatus($out_trade_no)){
                        $this->orderhandle($parameter);
                    }
                    return true;
                    //$this->success("支付成功!");
                }
                else{
                    //此处应该更新一下订单状态,商户自行增删操作
    //                log_result($log_name,"【支付成功】:
    ".$xml."
    ");
                    $this->error("UNKNOW ERROR");
                    
                }
                 
                //商户自行增加处理流程,
                //例如:更新订单状态
                //例如:数据库操作
                //例如:推送支付完成信息
            }
        }
        
        //查询订单
        public function orderQuery()
        {  
            if($this->checkorderstatus( I('post.out_trade_no') )){
                $this->ajaxReturn("SUCCESS");
            };
            $this->ajaxReturn("FAILD");
        }
        
        //在线交易订单支付处理函数
        //函数功能:根据支付接口传回的数据判断该订单是否已经支付成功;
        //返回值:如果订单已经成功支付,返回true,否则返回false;
        private function checkorderstatus($ordid){
            $ordstatus=M('OrderList')->where(array('ordid'=>$ordid))->getField('ordstatus');
            if($ordstatus==1){
                return true;
            }else{
                return false;    
            }
        }
    
        //处理订单函数
        //更新订单状态,写入订单支付后返回的数据
        private function orderhandle($parameter){
            $ordid=$parameter['out_trade_no'];
            $data['payment_trade_no']      =$parameter['transaction_id'];
            $data['payment_trade_status']  =$parameter['result_code'];
            $data['payment_notify_time']   =$parameter['time_end'];
            $data['payment_buyer_email']   =$parameter['openid'];
            $data['ordstatus']             =1;
            M('OrderList')->where(array('ordid'=>$ordid))->save($data);
            
            $Order = M('OrderList')->where(array('ordid'=>$ordid))->find();
            
            $ship_due_date = M("ShipInfo")->where(array('id'=>$Order['shipinfoid']))->find();
            if( $ship_due_date['due_date'] > time() ){
                $due_date = $ship_due_date['due_date']+($Order['ordbuydays']*86400);
            }else{
                $due_date = strtotime("+".$Order['ordbuydays']." day");
            }
            
            M('ShipInfo')->where(array('id'=>$Order['shipinfoid']))->save(array('due_date'=>$due_date,'status'=>1,'top'=>1));
            return ;
        } 
        
        
        
    }

    [title]

    二维码生成页面的html,目录位置ApplicationHomeViewdefaultWxpayqrcode.html

    [/title]

    <extend name="Base/common"/>
    
    
    <block name="body">
    <div class="center clearfix">
        <div class="bread">
        <a class="link" href="/">首页&gt;</a><span class="on">支付页面</span>
    	</div>
        <div class="pay_con_zl">
           
            <div class="p_tit_zl">支付页面</div>
          <div class="p_info_zl">
               <p>标题:{$title}</p>
               <p>支付金额:<span style="font-size:24px; font-weight:bold; color:#F00;">¥{$total_fee}元</span>,请使用微信扫描下方二维码完成支付<span style="padding-left:20px; color:#F00;">2小时之内,请尽快扫描支付</span></p>          
               <P><img alt="扫码支付" src="https://www.jiloc.com/wp-content/uploads/20170409040501NP4.jpg" style="150px;height:150px;"/></P>
            </div>
            
        </div>
    </div>
    <script language="">
    function Check(){
        var out_trade_no = "{$out_trade_no}";
        $.post("{:U('wxpay/orderQuery')}", { out_trade_no: out_trade_no},
            function(data){
                if(data == "SUCCESS"){
                    window.location = '{:U("my/paystatus",array("ordtype"=>"payed"))}';
                }
        });
    }
    window.setInterval("Check()",3000); 
    </script>
    </block>

    表单提交以后则跳转到二维码生成页面,提交地址:/wxpay/qrcode ,效果如下图:

    微信客户端支付成功以后,该页面会自动跳转到支付成功页面。

    [title]回调数据库表建立[/title]

    [title]微信平台配置[/title]

    微信公众平台上的配置了,这里我遇到过问题,如果有在这里遇到问题的同学请留言,比如出现了access_deined或者access_notallowed等问题,这都可能是因为这里配置不对。
    请看配置过程截图:

    支付授权目录设置为:http://laoji.org/wxpay/

    [title]注意:[/title]

    微信支付订单中的totla_fee的单位为分,比如1元,传值为100(分)

  • 相关阅读:
    【Solr】copy字段的应用
    【Solr】Solr的安装部署
    【UEditor】 UEditor整合项目上传资源到阿里云服务器
    【Bootstrap】Bootstrap和Java分页-第二篇
    【Bootstrap】Bootstrap和Java分页-第一篇
    工作那点小事
    ubuntu安装mongodb
    mybatis插入返回主键
    linux查看端口占用命令
    ubuntu安装ssh
  • 原文地址:https://www.cnblogs.com/qxandxt/p/10553618.html
Copyright © 2011-2022 走看看