thinkcmf+jsapi 实现微信支付

Easter79
• 阅读 872

首先从小程序端接收订单号、金额等参数,然后后台进行统一下单,把微信支付的订单号返回,在把订单号发送给前台,前台拉起支付,返回参数后更改支付状态。。。

回调

 public function notify() {
 $wechat=Db::name('wechat')->where('status',1)->find();

        //$post = $GLOBALS['HTTP_RAW_POST_DATA']; 
        $post = file_get_contents("php://input"); //接受POST数据XML个数


        // $order_over_test['openid']=$post;
        // Db::name('order_over')->insert($order_over_test);

        $post_data  = $this->xml_to_array($post);
       
     


        //输出订单号
        $order_sn = $post_data['out_trade_no'];

        $order_over['order_sn']=$order_sn;
        $order_over['money']=$post_data['total_fee'];
        $order_over['openid']=$post_data['openid'];
        $order_over['time_end']=$post_data['time_end'];

        $order_update['status']='1';

       // Db::name('order_over')->insert($order_over);

        $order_info=Db::name('order')->where('order_id',$order_sn)->find();

         if ($post_data['return_code'] == 'SUCCESS') {
         
            //判断证书是否正确
            // if ($postSign != $user_sign) {
            //     Log::write('签名不匹配');
            //     exit;
            // }
           if ($order_info['status'] != '1') {
               
               Db::name('order_over')->insert($order_over);
               $result=Db::name('order')->where('order_id', $order_sn)->update($order_update);
           }
            
             return 'success';
         
        } else {
          
            return 'error';
             //$this->error('error!');
        }
}

     public function xmlToArray($xml)
     {
         $p = xml_parser_create();
         xml_parse_into_struct($p, $xml, $vals, $index);
         xml_parser_free($p);
         $data = "";
         foreach ($index as $key => $value) {
             if ($key == 'xml' || $key == 'XML') continue;
             $tag = $vals[$value[0]]['tag'];
             $value = $vals[$value[0]]['value'];
             $data[$tag] = $value;
         }
         return $data;

     }


   public function xml_to_array($xml){
        if(!$xml){
            return false;
        }
        //将XML转为array
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $data;
    }

   public static function ToUrlParams($data)
               {
                   $buff = "";
                   foreach ($data as $k => $v)
                   {
                       if($k != "sign" && $v != "" && !is_array($v)){
                           $buff .= $k . "=" . $v . "&";
                       }
                   }

                   $buff = trim($buff, "&");
                   return $buff;
               }
         

统一下单

 public function getwxpay($orderSn,$money)
{
   // $orderSn=$orderSn;
  $body='广告投放';
   //$orderSn='HB14257311281654';
   //$money= '1';  
  $money=$money*100;
   $wechat=Db::name('wechat')->where('status',1)->find();
   $order_id=$orderSn;
   
   // $money= $money;                     //充值金额 微信支付单位为分
  
   $appid  = $wechat['appid'];    //应用APPID
   $mch_id =$wechat['mch_id'];                  //微信支付商户号
   $KEY    = $wechat['key'];                 //微信商户API密钥
   $out_trade_no = $orderSn ;//平台内部订单号
   $nonce_str = $this->rand_code();//随机字符串
  // $openid='oM0TH0nyMtlyrP_J8cOL70oLYaCw';
   $openid=session('openid');

           //获取系统的配置
         
           //$nonce_str = $this->rand_str(12);//随机字符串
           $notify_url = "http://**********************t/Wxnotify/notify";  //支付完成回调地址url,不能带参数
         
           $spbill_create_ip = get_client_ip();
           $trade_type = 'JSAPI';//交易类型 默认JSAPI

           //这里是按照顺序的 因为下面的签名是按照(字典序)顺序 排序错误 肯定出错
           $post['appid'] = $appid;
           $post['body'] = $body;
           $post['mch_id'] = $mch_id;
           $post['nonce_str'] = $nonce_str;//随机字符串
           $post['notify_url'] = $notify_url;
           $post['openid'] = $openid;
           $post['out_trade_no'] = $out_trade_no;
           $post['spbill_create_ip'] = $spbill_create_ip;//服务器终端的ip
           $post['total_fee'] = intval($money);        //总金额 最低为一分钱 必须是整数
           $post['trade_type'] = $trade_type;
           $sign = $this->MakeSign($post, $KEY);              //签名
           $this->sign = $sign;

           $post_xml = "
                   <xml>
                       <appid>$appid</appid> 
                       <mch_id>$mch_id</mch_id>
                       <nonce_str>$nonce_str</nonce_str>
                       <body>$body</body>
                       <notify_url>$notify_url</notify_url>
                       <openid>$openid</openid>
                       <out_trade_no>$out_trade_no</out_trade_no>
                       <spbill_create_ip>$spbill_create_ip</spbill_create_ip>
                       <total_fee>{$post["total_fee"]}</total_fee>
                       <trade_type>$trade_type</trade_type>
                       <sign>$sign</sign>
                   </xml>";

           //统一下单接口prepay_id
           $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
           $xml = $this->http_request($url, $post_xml);     //POST方式请求http

           $array = $this->xml2array($xml);               //将【统一下单】api返回xml数据转换成数组,全要大写

           $array['my_sign'] = $sign;
           $array['post_xml'] = $post_xml;
           $array['source_xml'] = $xml;
           
           if ($array['RETURN_CODE'] == 'SUCCESS' && $array['RESULT_CODE'] == 'SUCCESS') {
               $time = time();
               $tmp = '';                            //临时数组用于签名
               $tmp['appId'] = $appid;
               $tmp['nonceStr'] = $nonce_str;
               $tmp['package'] = 'prepay_id=' . $array['PREPAY_ID'];
               $tmp['signType'] = 'MD5';
               $tmp['timeStamp'] = "$time";


               // $data['state'] = 1;
               $data['timeStamp'] = "$time";           //时间戳
               $data['nonceStr'] = $nonce_str;         //随机字符串
               $data['signType'] = 'MD5';              //签名算法,暂支持 MD5
               $data['package'] = 'prepay_id='.$array['PREPAY_ID'];   //统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=*
               $data['paySign'] = $this->MakeSign($tmp, $KEY);       //签名,具体签名方案参见微信公众号支付帮助文档;
               $data['prepay_id'] = $array['PREPAY_ID'];
               $data['out_trade_no'] = $out_trade_no;
               $data['order_id'] = $order_id;
           } else {
               // $data['statusCode'] = ;
               $data['statusMsg'] = "请求错误";
               $data['data']['RETURN_CODE'] = $array['RETURN_CODE'];
               $data['data']['RETURN_MSG'] = $array['RETURN_MSG'];
           }

         
           return $data;
       
       }
   







    public function postXmlCurl($xml,$url,$second = 30){
       $ch = curl_init();
       //设置超时
       curl_setopt($ch, CURLOPT_TIMEOUT, $second);
       curl_setopt($ch,CURLOPT_URL, $url);
       curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
       curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);
       //设置header
       curl_setopt($ch, CURLOPT_HEADER, FALSE);
       //要求结果为字符串且输出到屏幕上
       curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
       //post提交方式
       curl_setopt($ch, CURLOPT_POST, TRUE);
       curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
       //运行curl
       $data = curl_exec($ch);
       //返回结果
       if($data){
           curl_close($ch);
           return $data;
       }else{
           $error = curl_errno($ch);
           curl_close($ch);
           echo "curl出错,错误码:$error"."<br>";
       }
   }
   




    //生成签名
       public function MakeSign($params, $KEY)
       {
           //签名步骤一:按字典序排序数组参数
           ksort($params);
           $string = $this->ToUrlParams($params);  //参数进行拼接key=value&k=v
           //签名步骤二:在string后加入KEY
           $string = $string . "&key=" . $KEY;
           //签名步骤三:MD5加密
           $string = md5($string);
           //签名步骤四:所有字符转为大写
           $result = strtoupper($string);
           return $result;
       }

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

               $buff = trim($buff, "&");
               return $buff;
           }
     
 

       //发送http请求

           public function http_request($url, $data = null, $headers = array())
           {
               $curl = curl_init();
               if (count($headers) >= 1) {
                   curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
               }
               curl_setopt($curl, CURLOPT_URL, $url);
               curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
               curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
       //
               $zs1 = CMF_ROOT . "cert/apiclient_cert.pem";
               $zs2 = CMF_ROOT . "cert/apiclient_key.pem";



       //        curl_setopt ( $curl, CURLOPT_SSLCERT, $zs1 );
       //        curl_setopt ( $curl, CURLOPT_SSLKEY, $zs2 );
               //设置证书
               //使用证书:cert 与 key 分别属于两个.pem文件
               curl_setopt($curl, CURLOPT_SSLCERTTYPE, 'PEM');
               curl_setopt($curl, CURLOPT_SSLCERT, $zs1);
               curl_setopt($curl, CURLOPT_SSLKEYTYPE, 'PEM');
               curl_setopt($curl, CURLOPT_SSLKEY, $zs2);

               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;
           }
      //获取xml里面数据,转换成array
         public function xml2array($xml)
         {
             $p = xml_parser_create();
             xml_parse_into_struct($p, $xml, $vals, $index);
             xml_parser_free($p);
             $data = "";
             foreach ($index as $key => $value) {
                 if ($key == 'xml' || $key == 'XML') continue;
                 $tag = $vals[$value[0]]['tag'];
                 $value = $vals[$value[0]]['value'];
                 $data[$tag] = $value;
             }
             return $data;

         }

    //随机字符串
         public function rand_code($length = 16) {

             $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

             $str = "";

             for ($i = 0; $i < $length; $i++) {

               $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);

             }

             return $str;

           }

           public function ToXml($data=array())

               {
                   if(!is_array($data) || count($data) <= 0)
                   {
                      return '数组异常';
                   }

                   $xml = "<xml>";
                   foreach ($data as $key=>$val)
                   {
                       if (is_numeric($val)){
                           $xml.="<".$key.">".$val."</".$key.">";
                       }else{
                           $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
                       }
                   }
                   $xml.="</xml>";
                   return $xml;
               }

前台页面拉起微信支付

<!DOCTYPE html>
<html>
<head>
  <title>订单支付 {$site_info.site_name|default=''}</title>
    <meta name="keywords" content="{$site_info.site_seo_keywords|default=''}"/>
    <meta name="description" content="{$site_info.site_seo_description|default=''}">
 
<include file="public@head"/>



</head>
<body >
<include file="public@top"/>
<hook name="before_head_end"/>
<!-- top -->
 


<div class="zt">
<div class="am-container">
 
<div>
  <div class="order_info">
    <h3 class="am-text-center">核实订单</h3>
</div>
   
   <div class="order_money am-text-center">
    <table class="am-table ">
      <tr>
        <td>订单号</td>
        <td class="am-text-right">{$order_info['order_id']}</td>
      </tr>
      <tr>
        <td>金额</td>
        <td class="am-text-right">{$order_info['money']}¥</td>
        <input type="hidden" name="money" id="money_input" value="">
      </tr>
    </table>
   </div>

  <div class="am-form-group">
  
   
   <button style="width:210px; height:50px; border-radius: 15px;background-color:#FE6714; border:0px #FE6714 solid; cursor: pointer;  color:white;  font-size:16px;" type="button" onclick="callpay()" >立即支付</button>
  
  </div>
</div>
</div>
</div>


<include file="public@footer"/>


<!--  <script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script> -->
 <script type="text/javascript">

  //调用微信JS api 支付
  function jsApiCall()
  {

    WeixinJSBridge.invoke(
      'getBrandWCPayRequest', {
         "appId":'{$wechat['appid']}',     //公众号名称,由商户传入     
         "timeStamp":'{$wxpay_status['timeStamp']}',       //时间戳,自1970年以来的秒数     
         "nonceStr":'{$wxpay_status['nonceStr']}', //随机串     
         "package":'{$wxpay_status['package']}',     
         "signType":"MD5",         //微信签名方式:     
         "paySign":'{$wxpay_status['paySign']}'//微信签名 
      }, 
      function(res){
        console.log(res);
        WeixinJSBridge.log(res.err_msg);
        //alert('err_code:'+res.err_code+'err_desc:'+res.err_desc+'err_msg:'+res.err_msg);
        //alert(res.err_code+res.err_desc+res.err_msg);
        //alert(res);
          if(res.err_msg == "get_brand_wcpay_request:ok"){  
            alert("支付成功!");
          window.location.href="http://m.sxcrcm.com";
          }else if(res.err_msg == "get_brand_wcpay_request:cancel"){  
            alert("用户取消支付!");  
          }else{  
            alert("支付失败!");  
          }  
      }
    );
  }
 
function callpay()
  {
    if (typeof WeixinJSBridge == "undefined"){
        if( document.addEventListener ){
            document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);
        }else if (document.attachEvent){
            document.attachEvent('WeixinJSBridgeReady', jsApiCall); 
            document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
        }
    }else{
        jsApiCall();
    }
  }

  </script>
</body>
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
Easter79
Easter79
Lv1
今生可爱与温柔,每一样都不能少。
文章
2.8k
粉丝
5
获赞
1.2k