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(分)

  • 相关阅读:
    leetcode 350. Intersection of Two Arrays II
    leetcode 278. First Bad Version
    leetcode 34. Find First and Last Position of Element in Sorted Array
    leetcode 54. Spiral Matrix
    leetcode 59. Spiral Matrix II
    leetcode 44. Wildcard Matching
    leetcode 10. Regular Expression Matching(正则表达式匹配)
    leetcode 174. Dungeon Game (地下城游戏)
    leetcode 36. Valid Sudoku
    Angular Elements
  • 原文地址:https://www.cnblogs.com/qxandxt/p/10553618.html
Copyright © 2011-2022 走看看