本文章將寫的是微信的app支付,安卓端app是用apicloud封裝的,ios端是用原生的,在這裏將項目裏面的微信支付後臺數據處理部分拿出來(順便複習一下),記錄一下。
首先我們來看一下微信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{
}
}
}
}