移動APP 微信支付完整過程(wxPay 方案一)


前兩天開始做移動端APP的微信支付,過程中遇到了一些問題,比如支付的過程中返回值總是:-1 {status:false},這些問題已經得到了解決。前人栽樹,后人盡管乘涼,那么分享一下整個支付過程(wxPay 方案一):

1、申請微信開發平台的賬號、創建移動應用、申請開發者資質認證(整個過程APICLOUD官方網站已經給出了相當明確的操作步驟,與實際操作沒有差異,按照文檔一步一步來,是沒有問題的),附帶鏈接地址:http://docs.apicloud.com/Others/Open-SDK-Integration-Guide/weChat

2、配置移動應用中 config.xml 文件

<feature name="wxPay">
    <param name="urlScheme" value="***"/>
    <param name="apiKey" value="***"/>
    <param name="apiSecret" value="***"/>
  </feature>

 

復制代碼


配置獲取方式說明以及截圖:從微信開發平台獲取,登錄微信開發平台 —>管理中心—>移動應用—>查看(urlScheme的值和apiKey相同)(微信開發平台鏈接:https://open.weixin.qq.com/

 

3、getOrderId(),將獲取預支付訂單號,建議將獲取預支付訂單號放置服務器端執行。(服務端代碼如下:)

$dataArr = array(
    'appid' => $appId,
    'mch_id' => $mchId,
    'nonce_str' => getNonceStr(),
    'body' => $body,
    'attach' => $attach,
    'out_trade_no' => getNonceStr(),
    'total_fee' => $totalFee,
    'spbill_create_ip' => $cIp,
    'notify_url' => $url,
    'trade_type' => 'APP'
);


//轉XML格式
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;
}


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

/**
* 格式化參數格式化成url參數
*/
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位)
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;
}


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對象
*/
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;
}




//=====================執行=======================
$sign = MakeSign($dataArr);//簽名生成
$dataArr['sign'] = $sign;

$xmlStr = createXML('xml', $dataArr);//統一下單xml數據生成
$reArr = explode('?>', $xmlStr);
$reArr = end($reArr);

$xml = curl('https://api.mch.weixin.qq.com/pay/unifiedorder', $reArr);//發送請求 統一下單數據

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

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

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


    //生成支付請求的簽名
    $paySign = 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
    );

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

4、預支付下單成功后,將拼接好的支付請求數據返回,也就是上述代碼中數組$payDatas(注意:第二次參與簽名的字段是:appid、partnerid、prepayid、noncestr、package、timestamp),app端代碼如下:

$.ajax({
            url:url,
            data:{
                body:body,
                attach:attach,
                total_fee:total_fee
            },
            dataType:"json",
            type:"post",
            success:function(data){


                if(data.payData != "error"){
                    var wxPay = api.require('wxPay');
                    wxPay.payOrder(data, function(ret, err) {

                        if (ret.status) {
                            //支付成功
                            alert('支付成功');
                            }



                        } else {
                            alert(err.code);

復制代碼

5、以上描述,已經親測沒有問題,如果代碼或敘述有問題的,歡迎各位大神指教批評;如果有幫到各位初學者的不勝榮幸;另外說下我之前遇到過支付過程中返回-1的問題:

官網上面payOrder()的參數為:appKey、orderId、mchId、nonceStr、timeStamp、package,就會以為參與第二次支付簽名的參數是這些,但其實並不是,

那么參與第二次支付簽名的參數是:appid、partnerid、prepayid、noncestr、package、timestamp,

生成簽名后,需要將payOrder()所需要的參數一一對應重新填寫(appKey==appid、orderId==prepayid、mchId==partnerid、nonceStr==noncestr、package==package、timeStamp==timestamp)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM