我集成了支付寶接口,可以支付成功,可是notify_url.php中始終好像沒有回調,所以按照官方文檔,我作了以下修改php
$verify_result = $alipayNotify->verifyNotify(); if($verify_result) { //商戶訂單號 $order_id = $_POST['out_trade_no']; //支付寶交易號 $trade_no = $_POST['trade_no']; //交易狀態 $trade_status = $_POST['trade_status']; //訂單總金額 $total_fee = floatval($_POST['total_fee']); //訂單支付時間 $pay_time = $_POST['gmt_payment']; //定製的錯誤機制 $user_debug=1; //退款狀態 $refund_status = $_POST['refund_status']; logResult('記錄付款後支付寶返回的相關信息[訂單編號]:'.$order_id.'[金額]:'.$total_fee.'[時間]:'.$pay_time.'[狀態]:'.$_POST['trade_status']); if ($_POST['trade_status'] == 'TRADE_SUCCESS' || $_POST['trade_status'] == 'TRADE_FINISHED') { } } else{ //驗證失敗 logResult('驗證失敗'); echo "fail"; }
其實就是用支付寶接口內部方法logResult方法記錄了回調的狀況,看看是否回調該文件而且看回調到了哪一步數組
再支付一次我發現log.txt文件中多了「驗證失敗」,所以我就判斷是$alipayNotify->verifyNotify();這個沒有返回正確的值安全
打開alipay_notify.class.php文件,找到verifyNotify方法,發現官方註釋了一段語句服務器
function verifyNotify(){ if(empty($_POST)) {//判斷POST來的數組是否爲空 return false; } else { //生成簽名結果 $isSign = $this->getSignVeryfy($_POST, $_POST["sign"]); //獲取支付寶遠程服務器ATN結果(驗證是不是支付寶發來的消息) $responseTxt = 'true'; if (! empty($_POST["notify_id"])) {$responseTxt = $this->getResponse($_POST["notify_id"]);} //寫日誌記錄 //if ($isSign) { // $isSignStr = 'true'; //} //else { // $isSignStr = 'false'; //} //$log_text = "responseTxt=".$responseTxt."\n notify_url_log:isSign=".$isSignStr.","; //$log_text = $log_text.createLinkString($_POST); //logResult($log_text); //驗證 //$responsetTxt的結果不是true,與服務器設置問題、合做身份者ID、notify_id一分鐘失效有關 //isSign的結果不是true,與安全校驗碼、請求時的參數格式(如:帶自定義參數等)、編碼格式有關 if (preg_match("/true$/i",$responseTxt) && $isSign) { return true; } else { return false; } } }
將如上代碼的註釋取消,再一次支付,再看log.txt發現寫入了以下代碼curl
執行日期:20140306121304
responseTxt=
notify_url_log:isSign=true,discount=0.00&payment_type=1&subject=訂單主題&trade_no=2014030615255398&buyer_email=287139270@qq.com&gmt_create=2014-03-06 12:12:55¬ify_type=trade_status_sync&quantity=1&out_trade_no=1394079155627&seller_id=2088211562160923¬ify_time=2014-03-06 12:13:03&trade_status=TRADE_SUCCESS&is_total_fee_adjust=N&total_fee=0.10&gmt_payment=2014-03-06 12:13:03&seller_email=aaaaaa@126.com&price=0.10&buyer_id=2088702034696988¬ify_id=ec0149b551db7c645e3e66a3058d3b067g&use_coupon=N&sign_type=MD5&sign=5a46cb0b739f659089330a28293e042e函數
因而咱們能夠發現isSign是經過了,那就是$this->getResponse($_POST["notify_id"]這個方法錯誤了post
function getResponse($notify_id) { $transport = strtolower(trim($this->alipay_config['transport'])); $partner = trim($this->alipay_config['partner']); $veryfy_url = ''; if($transport == 'https') { $veryfy_url = $this->https_verify_url; } else { $veryfy_url = $this->http_verify_url; } $veryfy_url = $veryfy_url."partner=" . $partner . "¬ify_id=" . $notify_id; $responseTxt = getHttpResponseGET($veryfy_url, $this->alipay_config['cacert']); return $responseTxt; }
能夠看出,該函數就是與支付寶進行通訊,而且這一次用到了支付寶的證書,我起初懷疑是證書的問題,其實全部的證書都是同樣的,不會根據商戶不一樣證書不一樣,不過也有多是證書路徑的問題$alipay_config['cacert'] = getcwd().'\\cacert.pem';有人也說改爲$alipay_config['cacert'] = getcwd().'/cacert.pem';不過我沒遇到這個問題this
固然最後要看alipay_core.function.php中的getHttpResponseGET方法了編碼
function getHttpResponseGET($url,$cacert_url) { $curl = curl_init($url); curl_setopt($curl, CURLOPT_HEADER, 0 ); // 過濾HTTP頭 curl_setopt($curl,CURLOPT_RETURNTRANSFER, 1);// 顯示輸出結果 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);//SSL證書認證 curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);//嚴格認證 curl_setopt($curl, CURLOPT_CAINFO,$cacert_url);//證書地址 $responseText = curl_exec($curl); //var_dump( curl_error($curl) );//若是執行curl過程當中出現異常,可打開此開關,以便查看異常內容 curl_close($curl); return $responseText; }
發現就是個curl_exec方法,因而就天然而然的懷疑是curl_exec方法被禁用了,打開phpinfo一看,果真是curl_exec被禁用了url
從中咱們能夠發現支付寶工做的原理,其實也沒有多複雜,支付成功後他會往notify_url post數據過來,系統會根據本地的證書,curl校驗