thinkcmf+jsapi 实现微信支付

Easter79
• 阅读 378

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

回调

 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>
点赞
收藏
评论区
推荐文章
浅梦一笑 浅梦一笑
5个月前
初学 Python 需要安装哪些软件?超级实用,小白必看!
编程这个东西是真的奇妙。对于懂得的人来说,会觉得这个工具是多么的好用、有趣,而对于小白来说,就如同大山一样。其实这个都可以理解,大家都是这样过来的。那么接下来就说一下python相关的东西吧,并说一下我对编程的理解。本人也是小白一名,如有不对的地方,还请各位大神指出01名词解释:如果在编程方面接触的比较少,那么对于软件这一块,有几个名词一定要了解,比如开发环
blmius blmius
1年前
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
刚刚好 刚刚好
5个月前
css问题
1、在IOS中图片不显示(给图片加了圆角或者img没有父级)<div<imgsrc""/</divdiv{width:20px;height:20px;borderradius:20px;overflow:h
小森森 小森森
5个月前
校园表白墙微信小程序V1.0 SayLove -基于微信云开发-一键快速搭建,开箱即用
后续会继续更新,敬请期待2.0全新版本欢迎添加左边的微信一起探讨!项目地址:(https://www.aliyun.com/activity/daily/bestoffer?userCodesskuuw5n)\2.Bug修复更新日历2.情侣脸功能大家不要使用了,现在阿里云的接口已经要收费了(土豪请随意),\\和注意
晴空闲云 晴空闲云
5个月前
css中box-sizing解放盒子实际宽高计算
我们知道传统的盒子模型,如果增加内边距padding和边框border,那么会撑大整个盒子,造成盒子的宽度不好计算,在实务中特别不方便。boxsizing可以设置盒模型的方式,可以很好的设置固定宽高的盒模型。盒子宽高计算假如我们设置如下盒子:宽度和高度均为200px,那么这会这个盒子实际的宽高就都是200px。但是当我们设置这个盒子的边框和内间距的时候,那
艾木酱 艾木酱
5个月前
快速入门|使用MemFire Cloud构建React Native应用程序
MemFireCloud是一款提供云数据库,用户可以创建云数据库,并对数据库进行管理,还可以对数据库进行备份操作。它还提供后端即服务,用户可以在1分钟内新建一个应用,使用自动生成的API和SDK,访问云数据库、对象存储、用户认证与授权等功能,可专
Wesley13 Wesley13
1年前
MySQL查询按照指定规则排序
1.按照指定(单个)字段排序selectfromtable_nameorderiddesc;2.按照指定(多个)字段排序selectfromtable_nameorderiddesc,statusdesc;3.按照指定字段和规则排序selec
Wesley13 Wesley13
1年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
helloworld_28799839 helloworld_28799839
5个月前
常用知识整理
Javascript判断对象是否为空jsObject.keys(myObject).length0经常使用的三元运算我们经常遇到处理表格列状态字段如status的时候可以用到vue
helloworld_34035044 helloworld_34035044
8个月前
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为