1. 程式人生 > >Thinkphp 5.1 微信小程式微信支付

Thinkphp 5.1 微信小程式微信支付

剛學習thinkPHP,小白一位,記錄一下,大神們不要笑!

Pay.php

<?php

namespace app\index\controller;

use think\exception\HttpResponseException;
use think\Response;
use lib\WeixinPay;

class Pay {
    public function payfee()
    {
        $appid='';
        $openid= input('openid');
        $mch_id='';
        $key='';
        $out_trade_no = $mch_id. time();
        $total_fee = input('total_fee');
        if($total_fee) {
            $body = "小天才電話手錶";
            $total_fee = floatval($total_fee*100);
        }

        $weixinpay = new WeixinPay($appid,$openid,$mch_id,$key,$out_trade_no,$body,$total_fee);
        $return=$weixinpay->pay();


        if($return){
            // 這裡返回資料
            $this->responseSuccess($return);
        }else{
            // 這裡返回錯誤碼及錯誤資訊,供客戶端呼叫
            $this->responseErro(400401,'沒有找到該使用者');
        }
    }
    public function notify ()
    {
        $postXml = $GLOBALS["HTTP_RAW_POST_DATA"]; //接收微信引數
        if (empty($postXml)) {
            return false;
        }
       //將xml格式轉換成陣列
        function xmlToArray($xml) {
            //禁止引用外部xml實體
            libxml_disable_entity_loader(true);
            $xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
            $val = json_decode(json_encode($xmlstring), true);
            return $val;
        }
        $attr = xmlToArray($postXml);
        $total_fee = $attr[total_fee];
        $open_id = $attr[openid];
        $out_trade_no = $attr[out_trade_no];
        $time = $attr[time_end];

    }
    protected function responseJson($code = 0, $msg = '', $data = [], $header = [])
    {
        $result = [
            'code' => $code,
            'msg' => $msg,
            'data' => $data,
        ];
        $response = Response::create($result, 'json')->header($header);
        throw new HttpResponseException($response);
    }

    /**
     * 返回錯誤資訊
     */
    protected function responseError($code, $msg = '', $header = []){
        $this->responseJson($code, $msg = '', $header);
    }

    /**
     * 返回正確資料
     */
    protected function responseSuccess($data, $msg = '', $header = []){
        $this->responseJson(0, $msg, $data, $header);
    }
}

WeixinPay.php

​
<?php

namespace lib;

class WeixinPay {


    protected $appid;
    protected $mch_id;
    protected $key;
    protected $openid;
    protected $out_trade_no;
    protected $body;
    protected $total_fee;
    function __construct($appid, $openid, $mch_id, $key,$out_trade_no,$body,$total_fee) {
        $this->appid = $appid;
        $this->openid = $openid;
        $this->mch_id = $mch_id;
        $this->key = $key;
        $this->out_trade_no = $out_trade_no;
        $this->body = $body;
        $this->total_fee = $total_fee;
    }


    public function pay() {
        //統一下單介面
        $return = $this->weixinapp();
        return $return;
    }


    //統一下單介面
    private function unifiedorder() {
        $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
        $parameters = array(
            'appid' => $this->appid, //小程式ID
            'mch_id' => $this->mch_id, //商戶號
            'nonce_str' => $this->createNoncestr(), //隨機字串
            'body' => $this->body,//商品描述
            'out_trade_no'=> $this->out_trade_no, //商戶訂單號
            'total_fee' => $this->total_fee,
            'spbill_create_ip' => '192.168.1.1', //終端IP
            'notify_url' => 'https://www.yourname.com/pay/notify', //通知地址  確保外網能正常訪問
            'openid' => $this->openid, //使用者id
            'trade_type' => 'JSAPI'//交易型別
        );
        //統一下單簽名
        $parameters['sign'] = $this->getSign($parameters);
        $xmlData = $this->arrayToXml($parameters);
        $return = $this->xmlToArray($this->postXmlCurl($xmlData, $url, 60));
        return $return;
    }


    private static 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_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20);
        curl_setopt($ch, CURLOPT_TIMEOUT, 40);
        set_time_limit(0);


        //執行curl
        $data = curl_exec($ch);
        //返回結果
        if ($data) {
            curl_close($ch);
            return $data;
        } else {
            $error = curl_errno($ch);
            curl_close($ch);
            throw new WxPayException("curl出錯,錯誤碼:$error");
        }
    }



    //陣列轉換成xml
    private function arrayToXml($arr) {
        $xml = "<root>";
        foreach ($arr as $key => $val) {
            if (is_array($val)) {
                $xml .= "<" . $key . ">" . arrayToXml($val) . "</" . $key . ">";
            } else {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            }
        }
        $xml .= "</root>";
        return $xml;
    }


    //xml轉換成陣列
    private function xmlToArray($xml) {


        //禁止引用外部xml實體


        libxml_disable_entity_loader(true);


        $xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);


        $val = json_decode(json_encode($xmlstring), true);


        return $val;
    }


    //微信小程式介面
    private function weixinapp() {
        //統一下單介面
        $unifiedorder = $this->unifiedorder();
//        print_r($unifiedorder);
        $parameters = array(
            'appId' => $this->appid, //小程式ID
            'timeStamp' => '' . time() . '', //時間戳
            'nonceStr' => $this->createNoncestr(), //隨機串
            'package' => 'prepay_id=' . $unifiedorder['prepay_id'], //資料包
            'signType' => 'MD5'//簽名方式
        );
        //簽名
        $parameters['paySign'] = $this->getSign($parameters);
        return $parameters;
    }


    //作用:產生隨機字串,不長於32位
    private function createNoncestr($length = 32) {
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }


    //作用:生成簽名
    private function getSign($Obj) {
        foreach ($Obj as $k => $v) {
            $Parameters[$k] = $v;
        }
        //簽名步驟一:按字典序排序引數
        ksort($Parameters);
        $String = $this->formatBizQueryParaMap($Parameters, false);
        //簽名步驟二:在string後加入KEY
        $String = $String . "&key=" . $this->key;
        //簽名步驟三:MD5加密
        $String = md5($String);
        //簽名步驟四:所有字元轉為大寫
        $result_ = strtoupper($String);
        return $result_;
    }


    ///作用:格式化引數,簽名過程需要使用
    private function formatBizQueryParaMap($paraMap, $urlencode) {
        $buff = "";
        ksort($paraMap);
        foreach ($paraMap as $k => $v) {
            if ($urlencode) {
                $v = urlencode($v);
            }
            $buff .= $k . "=" . $v . "&";
        }

        if (strlen($buff) > 0) {
            $reqPar = substr($buff, 0, strlen($buff) - 1);
        }
        return $reqPar;
    }


}

​

小程式程式碼

  pay: function (e) {
    var that = this
    var openid = wx.getStorageSync('openid');
    wx.request({
      url: app.data.servsers + '/index/pay/payfee',//改成你自己的連結
      header: {
        'Content-Type': 'application/x-www-form-urlencoded'
      },
      data: {
        total_fee: e.detail.value.total_fee,
        openid: openid,
      },
      method: 'POST',
      success: function (res) {
        console.log(res.data);
        console.log('調起支付');
        wx.requestPayment({
          'timeStamp': res.data.data.timeStamp,
          'nonceStr': res.data.data.nonceStr,
          'package': res.data.data.package,
          'signType': 'MD5',
          'paySign': res.data.data.paySign,
          'success': function (res) {
            console.log('支付成功');
            wx.showToast({
              title: '支付成功',
              icon: 'success',
              duration: 3000
            });
          },
          'fail': function (res) {
            console.log('支付失敗');
          wx.showToast({
            title: '支付失敗',
            ico:'success',
            duration:3000
          })
          },
          'complete': function (res) {
            console.log('complete');
          }
        });
      },
      fail: function (res) {
        console.log(res.data)
      }
    });
  },