PHP:微信小程序調用【統一下單】【微信支付】【支付回調】API;XML轉Array,Array轉XML方法(通用)

一、微信公衆號、微信小程序開發過程當中,第三方服務器與微信服務器數據交互,須要進行數據轉換,必須用到這兩個函數:前端

分別是xml_to_array、array_to_xml ;json

    /**
     * 輸出xml字符(數組轉換成xml)
     * @param $params 參數名稱
     * return string 返回組裝的xml
     **/
    public function array_to_xml( $params ){
        if(!is_array($params)|| count($params) <= 0)
        {
            return false;
        }
        $xml = "<xml>";
        foreach ($params as $key=>$val)
        {
            if (is_numeric($val)){
                $xml.="<".$key.">".$val."</".$key.">";
            }else{
                $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
            }
        }
        $xml.="</xml>";
        return $xml;
    }
    /**
     * 將xml轉爲array
     * @param string $xml
     * return array
     */
    public function xml_to_array($xml){
        if(!$xml){
            return false;
        }
        //將XML轉爲array
        //禁止引用外部xml實體
        libxml_disable_entity_loader(true);
        $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $data;
    }

二、拼接參數,將數組轉換成鍵值對形式的字符串:key=value&k=v小程序

    /**
     * 將參數拼接爲url: key=value&key=value
     * @param $params
     * @return string
     */
    public function ToUrlParams( $params ){
        $string = '';
        if( !empty($params) ){
            $array = array();
            foreach( $params as $key => $value ){
                $array[] = $key.'='.$value;
            }
            $string = implode("&",$array);
        }
        return $string;
    }

三、微信小程序生成簽名,makeSign($params,$KEY),第一個參數是微信官方文檔須要的參數;第二個參數是 申請微信支付得到的KEY微信小程序

    /**
     * 生成簽名, $KEY就是支付key
     * @return 簽名
     */
    public 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;
    }

四、微信小程序的簽名,總共須要三次;期中前兩次是必須的,最後一次儘可能加上數組

  4.1 第一次是【統一下單】,將全部須要的信息進行生成簽名,包括:服務器

$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); //簽名微信

..等等信息;app

 4.2 第二次是根據【統一下單】得到的"PREPAY_ID",和申請支付得到的KEY,進行makeSign簽名,返回給前端(如JS、APP等)進行調用wx.requestPayment({...})微信支付,包括:函數

$tmp['appId'] = $appid;
$tmp['nonceStr'] = $nonce_str;
$tmp['package'] = 'prepay_id='.$array['PREPAY_ID'];
$tmp['signType'] = 'MD5';
$tmp['timeStamp'] = "$time";post

//上面是簽名所需數據,下面是返回數據

$data['timeStamp'] = "$time";

$data['nonceStr'] = $nonce_str;

$data['signType'] = 'MD5';

$data['paySign'] = $this->MakeSign($tmp,$KEY);

$data['package'] = 'prepay_id='.$array['PREPAY_ID'];

($array是【統一下單】返回的數據,通過了xml_to_array處理)

  4.3 第三次是微信將支付結果通知給商戶,商戶須要進行處理通知結果。(通俗點:就是微信告訴你,用戶支付成功,你要給微信回一句話:我知道了。)

這個時候也須要makeSing簽名,具體代碼以下:

/* 微信支付完成,回調地址url方法  xiao_notify_url() */
    public function xiao_notify_url(){
        $KEY = '你申請微信支付的KEY';
        $post = post_data();    //接受POST數據
        $post_data = $this->xml_to_array($post);   //微信支付成功,返回回調地址url的數據:XML轉數組Array
        $postSign = $post_data['sign'];
        unset($post_data['sign']);    //這裏很重要哦,必定要將返回的sign剔除掉
        
        /* 微信官方提醒:
         *  商戶系統對於支付結果通知的內容必定要作【簽名驗證】,
         *  並校驗返回的【訂單金額是否與商戶側的訂單金額】一致,
         *  防止數據泄漏致使出現「假通知」,形成資金損失。
        */
        ksort($post_data);// 對數據進行排序
        //正常狀況微信是不會返回支付的key的,爲保萬一咱們判斷一下  --xzz 0622
        if($post_data['key']){
            $str = $this->ToUrlParams($post_data);//對數組數據拼接成key=value字符串
        }else{
            $str = $this->ToUrlParams($post_data).'&key='.$KEY; //這裏也必定要加上key,否則簽名就錯了
        }
        $user_sign = strtoupper(md5($str));   //再次生成簽名,與$postSign比較
        
        $where['crsNo'] = $post_data['out_trade_no'];
        $order_msg = M('home_order','xxf_witkey_')->where($where)->find();
        /*
         *  分別判斷返回狀態碼、返回簽名sign、返回訂單總金額,三者同時爲真,訂單交易成功,狀態修改成‘ok’
        */
        if($post_data['return_code']=='SUCCESS'&&$postSign==$user_sign&&$order_msg['order_amount']*100==$post_data['total_fee']){
            /*
            * 首先判斷,訂單是否已經更新爲ok,由於微信會總共發送8次回調確認
            * 其次,訂單已經爲ok的,直接返回SUCCESS
            * 最後,訂單沒有爲ok的,更新狀態爲ok,返回SUCCESS
            */
            if($order_msg['order_status']=='ok'){
                $this->return_success();
            }else{
                $updata['order_status'] = 'ok';
                if(M('home_order','xxf_witkey_')->where($where)->save($updata)){
                    $this->return_success();
                }
            }
        }else{
            echo '微信支付失敗';
        }
    }
    
    /*
     * 給微信發送確認訂單金額和簽名正確,SUCCESS信息 -xzz0521
     */
    private function return_success(){
        $return['return_code'] = 'SUCCESS';
        $return['return_msg'] = 'OK';
        $xml_post = '<xml>
                    <return_code>'.$return['return_code'].'</return_code>
                    <return_msg>'.$return['return_msg'].'</return_msg>
                    </xml>';
        echo $xml_post;exit;
    }

 五、再次提醒一下,這個代碼是給微信小程序用的,其餘的別照搬哦。

相關文章
相關標籤/搜索