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

前兩天開始作移動端APP的微信支付,過程當中遇到了一些問題,好比支付的過程當中返回值老是:-1 {status:false},這些問題已經獲得瞭解決。前人栽樹,後人儘管乘涼,那麼分享一下整個支付過程(wxPay 方案一):javascript

一、申請微信開發平臺的帳號、建立移動應用、申請開發者資質認證(整個過程APICLOUD官方網站已經給出了至關明確的操做步驟,與實際操做沒有差別,按照文檔一步一步來,是沒有問題的),附帶連接地址:docs.apicloud.com/Others/Open…java

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

<param name="urlScheme" value="***"/>
<param name="apiKey" value="***"/>
<param name="apiSecret" value="***"/>
複製代碼

複製代碼算法

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

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

$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);
複製代碼

}

複製代碼

四、預支付下單成功後,將拼接好的支付請求數據返回,也就是上述代碼中數組$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);
複製代碼

複製代碼

五、以上描述,已經親測沒有問題,若是代碼或敘述有問題的,歡迎各位大神指教批評;若是有幫到各位初學者的不勝榮幸;另外說下我以前遇到過支付過程當中返回-1的問題:參與第二次支付簽名的參數是:appid、partnerid、prepayid、noncestr、package、timestamp,生成簽名後,須要將payOrder()所須要的參數一一對應從新填寫(appKey==appid、orderId==prepayid、mchId==partnerid、nonceStr==noncestr、package==package、timeStamp==timestamp)。

相關文章
相關標籤/搜索