微信app支付,後臺處理(後臺數據處理)

本文章將寫的是微信的app支付,安卓端app是用apicloud封裝的,ios端是用原生的,在這裏將項目裏面的微信支付後臺數據處理部分拿出來(順便複習一下),記錄一下。

首先我們來看一下微信app官方給出的時序圖:

APPæ¯ä»æ¶åºå¾下面直接上代碼

public function wxorderOp(){
        $dataArr = array(
            'appid' => 'xxxx',
            'mch_id' => 'xxxx',
            'nonce_str' => $this->getNonceStr(),
            'body' => $pay['pay_sn'],
            'attach' => 'xxx',
            'out_trade_no' => $pay['pay_sn'],
            'total_fee' => 1,
            'spbill_create_ip' => '111.85.159.16',
            'notify_url' => 'xxxxxxxxxxx',//回調地址一定是要能訪問到的
            'trade_type' => 'APP'
        );
    $sign = $this->MakeSign($dataArr);//簽名生成
    $dataArr['sign'] = $sign;

    $xmlStr = $this->createXML('xml', $dataArr);//統一下單xml數據生成
    $reArr = explode('?>', $xmlStr);
    $reArr = end($reArr);
    $xml = $this->curl('https://api.mch.weixin.qq.com/pay/unifiedorder', $reArr);//發送請求 統一下單數據

    //解析返回的xml字符串
    $re = $this->xmlToObject($xml);

    //判斷統一下單是否成功
    if ($re['result_code'] == 'SUCCESS') {

        //支付請求數據
        $payData = array(
            'appid' => $re['appid'],
            'partnerid' => $re['mch_id'],
            'prepayid' => $re['prepay_id'],
            'noncestr' => $this->getNonceStr(),
            'package' => 'Sign=WXPay',
            'timestamp' => time()
        );


        //生成支付請求的簽名
        $paySign = $this->MakeSign($payData);

        $payData['sign'] = $paySign;

        //拼接成APICLOUD所需要支付數據請求
        $payDatas = array(
            'apiKey' => $re['appid'],
            'orderId' => $re['prepay_id'],
            'mchId' => $re['mch_id'],
            'nonceStr' => $payData['noncestr'],
            'package' => 'Sign=WXPay',
            'timeStamp' => $payData['timestamp'],
            'sign' => $paySign
        );

        //返回支付請求數據
        exit(json_encode($payDatas));
    } else {
        $re['payData'] = "error";
        exit(json_encode($re)) ;
       }
    }

 

//轉XML格式
    public function createXML($rootNode, $arr)
    {
        //創建一個文檔,文檔時xml的,版本號爲1.0,編碼格式utf-8
        $xmlObj = new DOMDocument('1.0', 'UTF-8');
        //創建根節點
        $Node = $xmlObj->createElement($rootNode);
        //把創建好的節點加到文檔中
        $root = $xmlObj->appendChild($Node);
        //開始把數組中的數據加入文檔
        foreach ($arr as $key => $value) {
            //如果是$value是一個數組
            if (is_array($value)) {
                //先創建一個節點
                $childNode = $xmlObj->createElement($key);
                //將節點添加到$root中
                $root->appendChild($childNode);
                //循環添加數據
                foreach ($value as $key2 => $val2) {
                    //創建節點的同時添加數據
                    $childNode2 = $xmlObj->createElement($key2, $val2);
                    //將節點添加到$childNode
                    $childNode->appendChild($childNode2);
                }
            } else {
                //創建一個節點,根據鍵和值
                $childNode = $xmlObj->createElement($key, $value);
                //把節點加到根節點
                $root->appendChild($childNode);
            }
        }
        //把創建好的xml保存到本地
        $xmlObj->save('xml/log.xml');
        $str = $xmlObj->saveXML();
//        echo $str;
        //返回xml字符串
        return $str;
    }


//封裝簽名算法
    public function MakeSign($arr)
    {
        //簽名步驟一:按字典序排序參數
        ksort($arr);
        $key = 'xxxxxxxxxxxxxxxxxxxxxxxx';
        $string = $this->ToUrlParams($arr);
        //簽名步驟二:在string後加入KEY
        $string = $string . "&key=" . $key;
        //簽名步驟三:MD5加密
        $string = md5($string);
        //簽名步驟四:所有字符轉爲大寫
        $result = strtoupper($string);
        return $result;
    }

    /**
     * 格式化參數格式化成url參數
     */
    public function ToUrlParams($arr)
    {
        $buff = "";
        foreach ($arr as $k => $v) {
            if ($k != "sign" && $v != "" && !is_array($v)) {
                $buff .= $k . "=" . $v . "&";
            }
        }

        $buff = trim($buff, "&");
        return $buff;
    }


//隨機字符串(不長於32位)
    public function getNonceStr($length = 32)
    {
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }


    public function curl($url, $post_data)
    {


        $headerArray = array(
            'Accept:application/json, text/javascript, */*',
            'Content-Type:application/x-www-form-urlencoded',
            'Referer:https://mp.weixin.qq.com/'
        );

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        // 對認證證書來源的檢查,0表示阻止對證書的合法性的檢查。
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        // 從證書中檢查SSL加密算法是否存在
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//關閉直接輸出
        curl_setopt($ch, CURLOPT_POST, 1);//使用post提交數據
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);//設置 post提交的數據
        curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.69 Safari/537.36');//設置用戶代理
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headerArray);//設置頭信息


        $loginData = curl_exec($ch);//這裏會返回token,需要處理一下。


        return $loginData;

        $token = array_pop($token);
        curl_close($ch);


    }

    /**
     * 解析xml文檔,轉化爲對象
     * @param  String $xmlStr xml文檔
     * @return Object         返回Obj對象
     */
    public function xmlToObject($xmlStr)
    {
        if (!is_string($xmlStr) || empty($xmlStr)) {
            return false;
        }
        // 由於解析xml的時候,即使被解析的變量爲空,依然不會報錯,會返回一個空的對象,所以,我們這裏做了處理,當被解析的變量不是字符串,或者該變量爲空,直接返回false
        libxml_disable_entity_loader(true);
        $postObj = json_decode(json_encode(simplexml_load_string($xmlStr, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        //將xml數據轉換成對象返回
        return $postObj;
    }

//回調數據處理

public function wxnotifyOp(){
    $xmldata = "
            <xml>
              <return_code><![CDATA[SUCCESS]]></return_code>
              <return_msg><![CDATA[OK]]></return_msg>
            </xml>";
    echo $xmldata;//告訴微信已接收到回調信息,如果微信收到商戶的應答不符合規範或超時,微信會判定本次通知失敗,重新發送通知,直到成功爲止(在通知一直不成功的情況下,微信總共會發起10次通知,通知頻率爲15s/15s/30s/3m/10m/20m/30m/30m/30m/60m/3h/3h/3h/6h/6h - 總計 24h4m)
    $data = array();
    $model_order = Model('order');
    $info = file_get_contents('php://input');
    $msg = (array)simplexml_load_string($info, 'SimpleXMLElement', LIBXML_NOCDATA);
    if($msg['return_code']=='SUCCESS'){
       //訂單數據處理
            }else{
                
            }
        }
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章