zoukankan      html  css  js  c++  java
  • php 微信公众号支付(小程序也是这么支付的)

    网上查看了很多微信支付程序,大多数是调用很多类,十分繁杂,出错概率很高。于是自己写的尽量简单一些,代码如下:

    //$appid和$appsecret 两个是在微信公众号设置的账号密码,记得appsecret要 保存好哦!$mch_id是微信商户id,要和微信开发公众平台绑定的商户id一致(我因为不这个不一致,当时没注意查看了两天代码)

    protected $appid = 'wx29c65112380c560';
    protected $AppSecret = 'f7241b0b8dc21j2sxe4215bc78c24d1';
    protected $mch_id = '150335221';

     /**

    *微信下单

    *@param total_price 下单金额 单位为/元 

        *@return 这一步返回prepay_id

        *@param $id为新订单的id

    */

    function wxpay($total_price='',$id=''){

    // header("Content-type:text/xml;charset=utf-8");

    if(empty($total_price)){

    //加个测试金额

    $total_price = 110;

    }

    $total_price = 0.01;

    $openid = $_SESSION['openid'];

    if(empty($openid)){

    //加个测试的openid

    $openid = 'opFig0knA1xDiGFGlZ9hpxq1aIXE';

    }

    //拼接商品订单号

    $body = '测试商品';

    $out_trade_no = date("YmdHis") . rand(100, 999);

    //更新支付宝订单号到数据表

    $this->ORDER->updateById(array('out_trade_no'=>$out_trade_no),

    $id);

            $noncestr = $this->rand2(10);

      $order = [

                'appid'=>$this->appid,

                'mch_id'=>$this->mch_id,

                'openid'=>$openid,

                'nonce_str'=>$noncestr,

                'body'=>'测试商品',

                'out_trade_no'=>$out_trade_no,//商户唯一订单号,可包含字母序

                'total_fee'=>(string)$total_price*100,//订单金额,单位/分所以乘以100

                'spbill_create_ip'=>$_SERVER['REMOTE_ADDR'],

                //产生订单号的服务器IP

                'notify_url' => App_Const::Domain_INDEX . 'notice',//接受微信异步通知地址

                'trade_type'=>'JSAPI',//交易类型

            ];

            //MD5处理,默认支持MD5

            $order['sign'] = $this->getSign($order);

            //转换成一维XML格式

            $xml = '<xml>';

            foreach($order as $k=>$v){

                $xml.='<'.$k.'><![CDATA['.$v.']]></'.$k.'>';

            }

            $xml.='</xml>';

    //这个key是商户平台加密的字符串,在商户平台一定要复制出来保存好,不要写成appsecret,容易混淆

            $KEY = '96e79218965eb72c92a549dd5ax112';//加密的字符串

            //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 );

            // if($response['return_code'] == "SUCCESS" && $response['result_code'] == "SUCCESS"){

                //根据微信支付返回的结果进行二次签名

                //二次签名所需的随机字符串

                $order["nonceStr"] = $noncestr;//随机字符串

                //二次签名所需的时间戳

                $order['timeStamp'] = time()."";

                //二次签名剩余参数的补充

                $secondSignArray = array(

                        "appId"=>$order['appid'],

                        "nonceStr"=>$order['nonceStr'],

                        //"package"=>"Sign=WXPay",

                        "package"=>"prepay_id=".$response['prepay_id'],

                        "signType"=>"MD5",

                        "timeStamp"=>$order['timeStamp'],

                );

                $data = $secondSignArray;

                $recharge_num = $order["out_trade_no"];

                $data['paySign'] =  $this->getSign($secondSignArray,$KEY);

                $data['prepay_id'] = $response['prepay_id'];

                $data['out_trade_no'] = $out_trade_no;

                // $output = array('data'=>$data ,'info'=>"success" ,'code'=>"200" ,'order_number'=>$recharge_num);

            $msg['status'] = 'success';

    //这个参数的data是前端调起微信支付窗口的数据,之所以写到msg里面,是因为我们公司前端这么要求,平时用单独 把data写出来就可以

            $msg['data'] = array(

            'timeStamp'=>time(),

            'nonceStr'=>$noncestr,

            'package'=>"prepay_id=".$response['prepay_id'],

            'signType'=>'MD5',

            'paySign'=> $data['paySign'],

            );

            echo json_encode($msg);die();

    }

    以上方法传输一个金额,一个订单id即可,完成上面的方法调用就算完成了,但是里面用到的封装function我需要列一下,代码如下:

    //这些直接复制就可以 了,不需要做任何修改

    function rand2($length = 16) {

            $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

            $str = "";

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

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

            }

            return $str;

        }

    //这个是生成sign的方法,直接复制就可以

         function getSign($params) {

    ksort($params); //将参数数组按照参数名ASCII码从小到大排序

    foreach ($params as $key => $item) {

      if (!empty($item)) {  //剔除参数值为空的参数

      $newArr[] = $key.'='.$item; // 整合新的参数数组

      }

    }

    $stringA = implode("&", $newArr);  //使用 & 符号连接参数

    $stringSignTemp = $stringA."&key="."96e79218965eb72c92a549d222a330112"; //拼接key

    // key是在商户平台API安全里自己设置的

    $stringSignTemp = MD5($stringSignTemp); //将字符串进行MD5加密

    $sign = strtoupper($stringSignTemp); //将所有字符转换为大写

    return $sign;

     }

    以上微信下单的方法,记得打印prepay_id,这个值非常关键,如果没有的话,即使调用返回值成功,下单也是没成功的。上面代码复制完了,数据返回给前端,前端调用支付窗口,然后付钱,微信会根据上面的回调地址返回成功或者失败。按照时间戳生成的那个订单号,也会在结果里返回,可以搞个 唯一的订单号作为标识,用来更新订单id。回调方法如下:

        /**

        *支付异步通知

        */

        function notice(){

            //获取微信的数据流

            $testxml = file_get_contents("php://input");

            $jsonxml = json_encode(simplexml_load_string($testxml,'SimpleXMLElement', LIBXML_NOCDATA));

            $result = json_decode($jsonxml,true);//转换成数组

            if($result){

                //如果成功了

                $out_tarde_no = $result['out_tarde_no'];

               if($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS'){

                    //支付状态 订单发货状态status  都修改掉

                     $this->ORDER->update(array('pay_status'=>2,'status'=>2),array('out_trade_no'=>$result['out_trade_no']));

                }else{

                    $this->ORDER->update(array('pay_status'=>3),array('out_trade_no'=>$result['out_trade_no']));

                }

            }else{

              //加一条测试,如果调用接口但是没有成功

               $this->ORDER->update(array('pay_status'=>22),array('id'=>10));

            }

        }

    注意回调结果是返回数据流,处理数据流然后根据out_trade_no字段来更新状态的,写到这里,整个微信支付代码就算结束了,谢谢大家观看!

  • 相关阅读:
    xp安装IIS admexs.dll问题
    MySql 牛哥推荐有空看看
    PHP常用类型判断函数
    GET和POST的真正区别
    许多真理
    PHP file_put_contents() 函数
    Intellijidea建javaWeb以及Servlet简单实现
    新手上路,配置阿里云CentOS服务器LAMP
    php的socket通信
    PHP常用的一些数组操作总结
  • 原文地址:https://www.cnblogs.com/ayanboke/p/9335383.html
Copyright © 2011-2022 走看看