注意點:html
一、簽名是倆次簽名,第一次,是獲取prepay_id時候,第二次簽名是最後返回結果的時候,所謂簽名就是對所傳遞參數的一個加密操做;json
二、加簽方式默認md5就能夠,若是要改爲HMAC-SHA256,須要在第一次簽名時候,傳遞參數:$newPara["sign_type"] = "HMAC-SHA256"; 而後在簽名加密的時候,使用:$String = hash_hmac("sha256",參數拼接字符串,密鑰);api
三、使用的密鑰,不是AppSecret,而是在微信商戶平臺上本身設定的api密鑰 32位;數組
四、重點:body參數格式:應用市場上的APP名字-實際商品名稱,好比:每天愛消除-遊戲充值。安全
代碼:服務器
$wx = new TegWXPay(); $res = $wx->weChatPay(訂單號,金額,商品名稱); echo $res; exit; //weixinpay class class TegWXPay{ private $config = array( 'appid' => "", /*微信開放平臺上的應用id*/ 'mch_id' => "", /*微信申請成功以後郵件中的商戶id*/ 'api_key' => "", /*在微信商戶平臺上本身設定的api密鑰 32位*/ 'notify_url' => '', /*自定義的回調程序地址*/ 'appname' => '' //app名稱 ); //入口函數 public function weChatPay($order_num,$price,$subject) { $json = array(); //生成預支付交易單的必選參數: $newPara = array(); //應用ID $newPara["appid"] = $this->config['appid']; //商戶appid; //商品描述 $newPara["body"] = $this->config['appname']."-".$subject; //設備號 $newPara["device_info"] = "WEB"; //商戶號 $newPara["mch_id"] = $this->config['mch_id']; //商戶id //隨機字符串,這裏推薦使用函數生成 $newPara["nonce_str"] = $this->createNoncestr(); //通知地址,注意,這裏的url裏面不要加參數 $newPara["notify_url"] = $this->config['notify_url'];//支付成功後的回調地址; //商戶訂單號,這裏是商戶本身的內部的訂單號 $newPara["out_trade_no"] = $order_num; //簽名類型 HMAC-SHA256 MD5 $newPara["sign_type"] = "MD5"; //終端IP $newPara["spbill_create_ip"] = $this->get_client_ip(); //總金額 $newPara["total_fee"] = $price; //交易類型 $newPara["trade_type"] = "APP"; $key = $this->config['api_key']; //密鑰:在商戶後臺我的安全中心設置 //第一次簽名 $newPara["sign"] = $this->appgetSign($newPara,$key); //echo json_encode($newPara); //exit; //把數組轉化成xml格式 $xmlData = $this->arrayToXml($newPara); $get_data = $this->sendPrePayCurl($xmlData); //返回的結果進行判斷。 if($get_data['return_code'] == "SUCCESS" && $get_data['result_code'] == "SUCCESS") { //根據微信支付返回的結果進行二次簽名 //二次簽名所需的隨機字符串 $newPara["nonce_str"] = $this->createNoncestr(); //二次簽名所需的時間戳 $newPara['timeStamp'] = time().""; //二次簽名剩餘參數的補充 $secondSignArray = array( "appid"=>$newPara['appid'], "noncestr"=>$newPara['nonce_str'], "package"=>"Sign=WXPay", "prepayid"=>$get_data['prepay_id'], "partnerid"=>$newPara['mch_id'], "timestamp"=>$newPara['timeStamp'], ); $json['success'] = 1; $json['ordersn'] = $newPara["out_trade_no"]; //訂單號 $json['order_arr'] = $secondSignArray; //返給前臺APP的預支付訂單信息 $json['order_arr']['sign'] = $this->appgetSign($secondSignArray,$key); //預支付訂單簽名 $json['data'] = "預支付完成"; //預支付完成,在下方進行本身內部的業務邏輯 /*****************************/ //return json_encode($json); $json['order_arr']['nonce_str'] = $secondSignArray['noncestr']; $json['order_arr']['prepay_id'] = $secondSignArray['prepayid']; $json['order_arr']['return_code'] = 'SUCCESS'; $json['order_arr']['return_msg'] = 'OK'; $test['pay_code'] = $json['order_arr']; return json_encode($test); }else{ $json['success'] = 0; $json['error'] = $get_data['return_msg']; return json_encode($json); } } //將數組轉換爲xml格式 public function arrayToXml($arr) { $xml = "<xml>"; foreach ($arr as $key=>$val) { //if (is_numeric($val)) if(false) { $xml.="<".$key.">".$val."</".$key.">"; } else $xml.="<".$key."><![CDATA[".$val."]]></".$key.">"; } $xml.="</xml>"; return $xml; } //發送請求 public function sendPrePayCurl($xml,$second=30) { $url = "https://api.mch.weixin.qq.com/pay/unifiedorder"; $ch = curl_init(); curl_setopt($ch,CURLOPT_URL, $url); curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE); curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE); //設置header curl_setopt($ch, CURLOPT_HEADER, FALSE); //要求結果爲字符串且輸出到屏幕上 curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); //post提交方式 curl_setopt($ch, CURLOPT_POST, TRUE); curl_setopt($ch, CURLOPT_POSTFIELDS, $xml); //運行curl $data = curl_exec($ch); curl_close($ch); $data_xml_arr =$this->XMLDataParse($data); if($data_xml_arr) { return $data_xml_arr; } else { $error = curl_errno($ch); echo "curl出錯,錯誤碼:$error"."<br>"; //echo "<a href='http://curl.haxx.se/libcurl/c/libcurl-errors.html'>錯誤緣由查詢</a></br>"; curl_close($ch); return false; } } //xml格式數據解析函數 public function XMLDataParse($data) { $xml = simplexml_load_string($data,NULL,LIBXML_NOCDATA); $array = json_decode(json_encode($xml),true); return $array; } //隨機字符串 public function createNoncestr( $length = 32 ) { $chars = "abcdefghijklmnopqrstuvwxyz0123456789"; $str =""; for ( $i = 0; $i < $length; $i++ ) { $str.= substr($chars, mt_rand(0, strlen($chars)-1), 1); } return $str; } /* * 格式化參數格式化成url參數 生成簽名sign */ public function appgetSign($Obj,$appwxpay_key) { foreach ($Obj as $k => $v) { $Parameters[$k] = $v; } //簽名步驟一:按字典序排序參數 ksort($Parameters); $String = $this->formatBizQueryParaMap($Parameters, false); //echo '【string1】'.$String.'</br>'; //簽名步驟二:在string後加入KEY if($appwxpay_key){ $String = $String."&key=".$appwxpay_key; } //echo "【string2】".$String."</br>"; //簽名步驟三:MD5加密 $String = md5($String); //HMAC-SHA256簽名方式 //$String = hash_hmac("sha256",$String,$appwxpay_key); //echo "【string3】 ".$String."</br>"; //簽名步驟四:全部字符轉爲大寫 $result_ = strtoupper($String); //echo "【result】 ".$result_."</br>"; return $result_; } //按字典序排序參數 public function formatBizQueryParaMap($paraMap, $urlencode) { $buff = ""; ksort($paraMap); foreach ($paraMap as $k => $v) { if($urlencode) { $v = urlencode($v); } //$buff .= strtolower($k) . "=" . $v . "&"; $buff .= $k . "=" . $v . "&"; } $reqPar; if (strlen($buff) > 0) { $reqPar = substr($buff, 0, strlen($buff)-1); } return $reqPar; } //獲取當前服務器的IP public function get_client_ip() { if ($_SERVER['REMOTE_ADDR']) { $cip = $_SERVER['REMOTE_ADDR']; } elseif (getenv("REMOTE_ADDR")) { $cip = getenv("REMOTE_ADDR"); } elseif (getenv("HTTP_CLIENT_IP")) { $cip = getenv("HTTP_CLIENT_IP"); } else { $cip = "unknown"; } return $cip; } }