php 微信小程序支付

php 微信小程序支付  php

直接貼代碼:前端

前端測試按鈕wxml:json

<view class="container">
  <text class="name">當前選擇:《參加活動》 ¥0.01</text>
  <view class="pay"   bindtap="onTap">確認支付</view>
</view>

wxss:小程序

.container {
  padding: 50rpx;
}

.pay {
  margin-top: 30rpx;
  color: #fff;
  background-color: #1fb922;
}

js:後端

Page({

    /**
     * 頁面的初始數據
     */
    onTap () {
      console.log('6666');
        let _self = this;
        _self._togglePay();
        //發起網絡請求
        wx.request({
            url: '付款url',
            method: "POST",
            data: {
                openid: '',
                money:0.01
            },
            header: {
                "content-type": "application/x-www-form-urlencoded"
            },
            success(res) {
                var params = res.data.data;
                wx.requestPayment({
                    'timeStamp': String(params['timeStamp']),
                    'nonceStr': params['nonceStr'],
                    'package': params['package'],
                    'signType': params['signType'],
                    'paySign': params['paySign'],
                    'success': function (res) {
                        wx.showToast({
                            title: '支付成功',
                            icon: 'success',
                            duration: 2000
                        })
                        _self._togglePay();
                    },
                    'fail': function (res) {
                        wx.showToast({
                            title: '支付失敗',
                            icon: 'none',
                            duration: 2000
                        })
                        _self._togglePay();
                    },
                })
            }
        })

    },

    _togglePay() {
        this.setData({
            pay: !this.data.pay
        });
    }

})

 

後端PHP代碼:微信小程序

首先是公共函數,處理數據用的:api

  // curl請求方法封裝
    private 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 Exception("curl出錯,錯誤碼:$error");
        }
    }

    //數組轉換成xml
    private function arrayToXml($arr) {
        $xml = "<xml>";
        foreach ($arr as $key => $val) {
            if (is_array($val)) {
                $xml .= "<" . $key . ">" . $this->arrayToXml($val) . "</" . $key . ">";
            } else {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            }
        }
        $xml .= "</xml>";
        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;
    }

    //做用:產生隨機字符串,不長於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 . "&";
        }
        $reqPar='';
        if (strlen($buff) > 0) {
            $reqPar = substr($buff, 0, strlen($buff) - 1);
        }

        return $reqPar;
    }

    /*生成訂單號*/
    private function out_trade_no(){
        //return date('YmdHis').md5($openid.time().rand(10,99));//32位
        return date('YmdHis',time()).time().rand(10,99);
    }

業務代碼:數組

//統一下單
    private function unifiedorder($body,$openid,$pay) {
        $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
        // 這裏的參數順序必定要按下面的,否則可能就一直報商戶號此功能未受權等錯誤
        $parameters = array(
            'appid' => $this->appid,                              // 小程序ID
            'body' => $body,                                         //支付標題
            'mch_id' => $this->mch_id,                          // 商戶號
            'nonce_str' => $this->createNoncestr(),             // 隨機字符串
            'notify_url' => $this->notify_url,                  //'https://shop.gdpress.cn/syw_jingzhun/index.php/Api/xiaochengxu/notify_url_api', // 通知地址 確保外網能正常訪問
            'openid' => $openid,                                // 用戶id
            'out_trade_no'=> $this->out_trade_no(),               // 商戶訂單號
            'spbill_create_ip' => Yii::$app->request->userIP,   // 終端IP ,這是YII2框架的寫法
            'total_fee' => floatval($pay * 100),           //支付金額 單位 分
            'trade_type' => 'JSAPI'                             // 交易類型
        );

        //統一下單簽名
        $parameters['sign'] = $this->getSign($parameters);
        $xmlData =  $this->arrayToXml($parameters);
        $return  =  $this->xmlToArray($this->postXmlCurl($xmlData, $url, 60));
        return $return;
    }

    //微信小程序支付接口  調用
    public function actionWxpay() {

        $body='小程序支付測試';
        $openid='';//付款者openid
        $pay='0.01';//支付金額
        //統一下單接口
        $unifiedorder = $this->unifiedorder($body,$openid,$pay);
        // 統一下單出錯,參數出錯等緣由
        if($unifiedorder['return_code'] == 'FAIL') {
            return Json::encode(['code'=>400,'msg'=>'支付失敗','data'=>$unifiedorder['return_msg']]);
        }

        // 對統一下單返回得參數進行處理
        $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 Json::encode(['code'=>200,'msg'=>'支付成功','data'=>$parameters]);
    }

支付成功回調:服務器

*微信支付的 異步通知 *回調地址*/
    public function actionNoticefy() {
        $xml = file_get_contents("php://input");
        //將服務器返回的XML數據轉化爲數組
        $data = $this->xmlToArray($xml);
        // 判斷簽名是否正確  判斷支付狀態
        if (($data['return_code'] == 'SUCCESS')) {//支付成功
            $result = $data;
            //獲取服務器返回的數據
            $out_trade_no = $data['out_trade_no'];      // 訂單單號
            $openid = $data['openid'];                  // 付款人openID
            $total_fee = floatval(($data['total_fee'])/100);      // 付款金額
            $transaction_id = $data['transaction_id'];  // 微信支付流水號
            $time_end = $data['time_end'];  // 處理時間

            //查找訂單
            $order=ActivityOrder::find()->where(['out_trade_no'=>$out_trade_no])->one();
            if ($order) {// 訂單存在
                $result=true;
            }else{// 訂單不存在,則建立訂單
                $activityOrder=new ActivityOrder();
                $activityOrder->out_trade_no=$out_trade_no;
                $activityOrder->openid=$openid;
                $activityOrder->activity_id=48;
                $activityOrder->status=1;
                $activityOrder->total_fee=$total_fee;
                $activityOrder->transaction_id=$transaction_id;
                $activityOrder->time_end=$time_end;
                $activityOrder->userIP=Yii::$app->request->userIP;
                $activityOrder->create_time=time();
                 if ($activityOrder->save()){
                     $result=true;
                 }else{
                     $result = false;
                 }
            }
        }else {//支付失敗
            $result = false;
        }
        // 返回狀態給微信服務器
        if ($result) {
            $str='<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
        }else{
            $str='<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[簽名失敗]]></return_msg></xml>';
        }

        return $str;
    }

注:本支付基於Yii2框架編寫,若用其餘框架,請自行改掉名稱等Yii2專有函數。微信

相關文章
相關標籤/搜索