前兩天開始作移動端APP的微信支付,過程當中遇到了一些問題,好比支付的過程當中返回值老是:-1 {status:false},這些問題已經獲得瞭解決。前人栽樹,後人儘管乘涼,那麼分享一下整個支付過程(wxPay 方案一):javascript
一、申請微信開發平臺的帳號、建立移動應用、申請開發者資質認證(整個過程APICLOUD官方網站已經給出了至關明確的操做步驟,與實際操做沒有差別,按照文檔一步一步來,是沒有問題的),附帶連接地址:http://docs.apicloud.com/Othe...java
二、配置移動應用中 config.xml 文件ajax
<feature name="wxPay">算法
<param name="urlScheme" value="***"/> <param name="apiKey" value="***"/> <param name="apiSecret" value="***"/>
</feature>
複製代碼json
配置獲取方式說明以及截圖:從微信開發平臺獲取,登陸微信開發平臺 —>管理中心—>移動應用—>查看(urlScheme的值和apiKey相同)(微信開發平臺連接:https://open.weixin.qq.com/)api
三、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;
}
/**
*/
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);
}
/**
*/
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)。