zoukankan      html  css  js  c++  java
  • php小程序支付代码(微信公众平台,完整版)

    1,wxpay.php 微信小程序支付(微信公众平台),微信公众号支付大同小异。希望对大家有所帮助,谢谢!内容如下:<?php
     
    //微信小程序支付代码详解
     
    //第一步,下单  支付前需要下单,调用了两个方法wxpay和wxapi
    /**
    *微信下单
    */
    function wxorders(){
     
            ini_set("display_errors", "On");
            error_reporting(E_ALL | E_STRICT);
     
    $kilometre = $_POST['kilometre'];
    $km = $kilometre/1000;//米数转化成公里
    //提交订单
    $data = array(
    'start_address'=>$_POST['startLoca'],//出发地址
    'end_address'=>$_POST['destLoca'],//目的地
    'start_time'=>strtotime(str_replace('.','-',$_POST['startTime'])),//开始时间
    'end_time'=>strtotime(str_replace('.','-',$_POST['endTime'])),//结束时间
    'km'=>$km,//公里数
    'seat'=>$_POST['seat'],//座位
    'borad_price'=>$_POST['basicPrice'],//上车价
    'per_km'=>$_POST['perKiloPrice'],//每公里单价
    'total_price'=>$_POST['cost'],//总价钱
    'contact'=>$_POST['name'],//联系人名
    'mobile'=>$_POST['phone'],//联系电话
    'status'=>'1',//状态
    'create_time'=>time(),//提交时间
    'type'=>$_POST['type'],//租车类型  小bus 大巴等
    'kelala'=>$_POST['session_key'],//标识符
    );
    $total_price = $_POST['cost'];//总价赋值
            //插入订单记录,此处状态为待付款
    $res = $this->baseModel->add('orders',$data);
            //根据标识符查询当前账号的openid
            $kelala = $_POST['session_key'];//用户的唯一标识
            $user = $this->baseModel->getRow('user','*',array('kelala'=>$kelala));
        //调用下单接口  $res为新订单的id
    $r = $this->wxpay($total_price,$user['openid']);
            //分别传总金额,用户openid,前面生成的订单id
            $a = $this->wxapi($total_price,$user['openid'],$r['prepay_id'],$res);
            //这里返回结果集合到前段,前段根据返回的参数调用微信支付界面,并且返回成功失败给后端,需要另外写接口接收
            echo $a;exit();
    }
     
    /**
    *微信下单
    *@param total_price 下单金额 单位为/元 
        *@return 这一步返回prepay_id
        *@param $id为新订单的id
    */
    function wxpay($total_price,$openid){
    //拼接商品订单号
    $body = '测试商品';
    $out_trade_no = date("YmdHis") . rand(100, 999);
            // //更新微信返回的订单号
            // $this->baseModel->updateById('orders',array('out_trade_no'=>$out_trade_no),$id);
      $order = [
                'appid'=>'',
                'mch_id'=>'',//商户id
                'openid'=>$openid,
                'nonce_str'=>$this->rand2(10),
                'body'=>'测试商品',
                'out_trade_no'=>$out_trade_no,//商户唯一订单号,可包含字母序
                'total_fee'=>$total_price*100,//订单金额,单位/分所以乘以100
                'spbill_create_ip'=>'123.12.12.123',//产生订单号的服务器IP
                'notify_url'=>'https://ww.baidu.com',//接受微信异步通知地址
                'trade_type'=>'JSAPI',//交易类型
            ];
            //MD5处理,默认支持MD5
            // $sign = md5($sign);
            $order['sign'] = $this->getSign($order);
            //转换成一维XML格式
            $xml = '<xml>';
            foreach($order as $k=>$v){
                $xml.='<'.$k.'><![CDATA['.$v.']]></'.$k.'>';
            }
            $xml.='</xml>';
     
            //CURL会话
            $ch = curl_init();
            // 设置curl允许执行的最长秒数
            curl_setopt($ch, CURLOPT_TIMEOUT, 3);
            curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
            curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,false);
            // 获取的信息以文件流的形式返回,而不是直接输出。
            curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
            //发送一个常规的POST请求。
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_URL, 'https://api.mch.weixin.qq.com/pay/unifiedorder');
            //要传送的所有数据
            curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
            // 执行操作
            $response = curl_exec($ch);
            //将xml格式的$response 转成数组
            $response = json_decode( json_encode( simplexml_load_string($response, 'SimpleXMLElement', LIBXML_NOCDATA) ), true );
            return $response;
    }
     
    //第二步,再次签名
    /**
        *再次签名
        *@param $total_fee 下单金额
        *@param $openid 当前用户openid $order_id 下单时传来的id
        * @param $id为新订单的id
        */
    function wxapi($total_fee,$openid,$order_id,$id){
             ini_set("display_errors", "On");
            error_reporting(E_ALL | E_STRICT);
            $out_trade_no = date("YmdHis") . rand(100, 999);
            //更新订单状态 此处状态更新为1
            $this->baseModel->updateById('orders',array('out_trade_no'=>$out_trade_no),$id);
     
            if(empty($total_fee)){
                echo json_encode(array('state'=>0,'Msg'=>'金额有误'));exit;
            }
            if(empty($openid)){
                echo json_encode(array('state'=>0,'Msg'=>'登录失效,请重新登录(openid参数有误)'));exit;
            }
            if(empty($order_id)){
                echo json_encode(array('state'=>0,'Msg'=>'自定义订单有误'));exit;
            }
            $appid =        '';//如果是公众号 就是公众号的appid;小程序就是小程序的appid
            $body =         '测试数据';
            $mch_id =       '';//商户id
            $KEY = '12ed7bd47d66f4ef7865f79b2194a94b';//加密的字符串  在公众号平台设置
            $nonce_str =    $this->rand2(10);//随机字符串
            $notify_url =   'https://www.baidu.com/';  //支付完成回调地址url,不能带参数
            $out_trade_no = $out_trade_no;//商户订单号
            // $spbill_create_ip = '123.12.12.123';
            $spbill_create_ip = $_SERVER['SERVER_ADDR'];
            $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($total_fee);        //总金额 最低为一分钱 必须是整数
            $post['trade_type'] = $trade_type;
            $sign = $this->MakeSign($post,$KEY);              //签名
            $this->sign = $sign;
        
            $post_xml = '<xml>
                   <appid>'.$appid.'</appid>
                   <body>'.$body.'</body>
                   <mch_id>'.$mch_id.'</mch_id>
                   <nonce_str>'.$nonce_str.'</nonce_str>
                   <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>'.$total_fee.'</total_fee>
                   <trade_type>'.$trade_type.'</trade_type>
                   <sign>'.$sign.'</sign>
                </xml> ';
        
            //统一下单接口prepay_id
            $xml = $this->http_request($url,$post_xml);     //POST方式请求http
            $array = $this->xml2array($xml);               //将【统一下单】api返回xml数据转换成数组,全要大写
            if($array['RETURN_CODE'] == 'SUCCESS' && $array['RESULT_CODE'] == 'SUCCESS'){
                $time = time();   
                $tmp='';                            //临时数组用于签名
                $tmp['appId'] = $appid;
                $tmp['nonceStr'] = $nonce_str;
                $tmp['package'] = 'prepay_id='.$order_id;
                $tmp['signType'] = 'MD5';
                $tmp['timeStamp'] = (string)$time;
        
                $data['state'] = 1;
                $data['timeStamp'] = (string)$time;           //时间戳
                $data['nonceStr'] = $nonce_str;         //随机字符串
                $data['signType'] = 'MD5';              //签名算法,暂支持 MD5
                $data['package'] = 'prepay_id='.$order_id;
                // = 'prepay_id='.'wx20180314162441c9c0b517a40292406177';   //统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=*
                $data['paySign'] = $this->MakeSign($tmp,$KEY);       //签名,具体签名方案参见微信公众号支付帮助文档;
                $data['out_trade_no'] = $out_trade_no;
        
            }else{
                $data['state'] = 0;
                $data['text'] = "错误";
                $data['RETURN_CODE'] = $array['RETURN_CODE'];
                $data['RETURN_MSG'] = $array['RETURN_MSG'];
            }
            //此处返回结果集合
            return json_encode($data);
        }
    //第三部,上面三个fuction为核心代码,下面的全部是封装的方法,可直接复制使用
    /**
    *生成签名算法
    */
    function getSign($array)
    {
        $pay_key = "12ed7bd47d66f4ef7865f79b2194a94b";
        unset($array['sign']);
        ksort($array);
        $stringA = urldecode(http_build_query($array));
        $stringSignTemp="$stringA&key=".$pay_key;
        return strtoupper(md5($stringSignTemp));
    }
     
     
    /**
    *生成不重复的字符串
    *@param $len 字符串长度
    *@return 随机字符串
    */
    function rand2($len)
       {
          $chars='ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz';
          $string=time();
          for(;$len>=1;$len--)
          {
              $position=rand()%strlen($chars);
              $position2=rand()%strlen($string);
              $string=substr_replace($string,substr($chars,$position,1),$position2,0);
         }
         return $string;
    }
     
     
     
        /**
         * 生成签名, $KEY就是支付key
         * @return 签名
         */
        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;
        }
     
     
         function ToUrlParams( $params ){
            $string = '';
            if( !empty($params) ){
                $array = array();
                foreach( $params as $key => $value ){
                    $array[] = $key.'='.$value;
                }
                $string = implode("&",$array);
            }
            return $string;
        }
     
         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;
        }
     
        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);
        
            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;
        }
  • 相关阅读:
    腾讯精选50题算法【二叉搜索树的最近公共祖先】
    潜水一周,我精心整理了两个超级有用的职场生存之道
    全球用尽IPv4的一点思考
    Leetcode算法【114. 二叉树展开为链表】
    【翻译】全新16英寸MacBook Pro评测:开发人员的梦想成真
    Medium高赞系列,如何正确的在Stack Overflow提问
    Typora+PicGo+GitHub实现md自带图床效果
    SpringBoot输出日志到文件
    Mybatis用SQL做自连表查询
    IDEA实用插件推荐及使用方法详解
  • 原文地址:https://www.cnblogs.com/ayanboke/p/8574349.html
Copyright © 2011-2022 走看看