微信支付回調驗證簽名:必定要驗證簽名,可能不形成僞造數據,或者數據庫造到灌水;php
<?php /** * 微信支付回調類 * @name CallbackAction.class.php * @author yangzl * @date(20180820) */ class CallbackAction extends Action{ /** * @param 獲取微信支付回調接口 * @return [type] [descripti * @date(20180820) * @author yangzl */ public function getPayMentCallBack(){ $curl_request = $_SERVER['REQUEST_METHOD']; //獲取請求方式 if($curl_request == 'POST'){ $xmldata=file_get_contents("php://input"); libxml_disable_entity_loader(true); //把微信支付回調結果寫入日誌 $this->writeLogs(RUNTIME_PATH.'Logs/','getPayMentCallBack',"\r\n-------------------".date('Y-m-d H:i:s')."微信支付回調結果---------\r\n---響應數據:".json_encode(simplexml_load_string($xmldata, 'SimpleXMLElement', LIBXML_NOCDATA))."\r\n------------\r\n"); //處理微信支付返回的xml數據 $data = json_encode(simplexml_load_string($xmldata, 'SimpleXMLElement', LIBXML_NOCDATA)); $sign_return = json_decode($data,true)['sign']; $sign = $this->appgetSign(json_decode($data,true)); //給微信返回接收成功通知,生成xml數據 $this->returnXml(); if($sign == $sign_return){ //把數據提交給訂單處理方法 $this->proOrders($data); } } } /* * 格式化參數格式化成url參數 生成簽名sign */ public function appgetSign($data){ require_once WEB_LIB."WxPay.Config.php"; $config = new WxPayConfig(); $appwxpay_key = $config->GetKey(); //簽名步驟一:按字典序排序參數 ksort($data); $String = $this->callbackToUrlParams($data); //簽名步驟二:在string後加入KEY if($appwxpay_key){ $String = $String."&key=".$appwxpay_key; } //簽名步驟三:MD5加密 $String = md5($String); //簽名步驟四:全部字符轉爲大寫 $result_ = strtoupper($String); return $result_; } /** * 格式化參數格式化成url參數 */ public function callbackToUrlParams($Parameters){ $buff = ""; foreach ($Parameters as $k => $v){ if($k != "sign" && $v != "" && !is_array($v)){ $buff .= $k . "=" . $v . "&"; } } $buff = trim($buff, "&"); return $buff; } /** * @param 拼裝xml數據返回 * @author yangzl <[<email address>]> */ public function returnXml(){ header("Content-type:text/xml;"); $xml = "<?xml version='1.0' encoding='UTF-8'?>\n"; $xml .= "<xml>\n"; $xml .= "<return_code>SUCCESS</return_code>\n"; $xml .= "<return_msg>OK</return_msg>\n"; $xml .= "</xml>\n"; echo $xml; } /** * @param 支付回調程序處理 * @author yangzl * @date(20180820) */ public function proOrders($data){ if (!$data) { $date = date("Y-m-d H:i:s",time()); log::write( "proOrders方法錯誤".$date); } //處理則返回數據入庫 分表 $orders_info = json_decode($data,true); $orders_model = new OrdersModel(); $branch_id = json_decode($orders_info['attach'],true)['branch_id']; //查詢排重 $result_pay_data = $orders_model->get_pay_data($branch_id,$orders_info['transaction_id']); if(!$result_pay_data){ //不存在 //存數據 $table_id = json_decode($orders_info['attach'],true)['table_id']; //根據tableid查詢桌臺信息 $tables_model = new TablesModel(); $table_info = $tables_model->get_table_by_id( $table_id, $branch_id); if($table_info['is_delete'] == '0'){ $title = $table_info['title']; } //回調支付信息 $pay_info = array( 'branch_id' => $branch_id, 'transaction_id' => $orders_info['transaction_id'], 'cash_fee' => sprintf("%.2f",$orders_info['cash_fee']/100), 'pay_type' => 1, 'mch_id' =>$orders_info['mch_id'], 'result_code' => $orders_info['result_code'] == 'SUCCESS' ? 1 : 0, 'orders_id' =>$orders_info['out_trade_no'], 'time_end' => $orders_info['time_end'], 'title' => $title, 'openid'=> $orders_info['openid'], 'pay_source' => 1, 'is_subscribe' => $orders_info['is_subscribe'] == 'Y' ? 1 : 0, //是否關注公衆帳號 'sub_mch_id' => $orders_info['sub_mch_id'], 'total_fee' =>sprintf("%.2f",$orders_info['total_fee']/100), 'bank_type' => $orders_info['bank_type'], ); //存數據 $add_data = $orders_model->add_pay_info($branch_id,$pay_info); if(!$add_data){ log::write( "支付數據存儲失敗".$orders_info['transaction_id']); return false; } if($orders_info['result_code'] == 'SUCCESS'){ //查詢訂單信息 // $order_data = $orders_model->get_orders_data($table_id, $branch_id); $order_data = $orders_model->get_orders_tem($table_id, $branch_id); if(!$order_data){ log::write( "查詢訂單信息失敗".time()); return false; } $this->writeLogs(RUNTIME_PATH.'Logs/','proOrders',"\r\n-------------------".date('Y-m-d H:i:s')."查詢訂單信息---------\r\n---響應數據:".json_encode($order_data)."\r\n------------\r\n"); //數據處理 $data_handle = $orders_model->data_handle($order_data,$table_id,$branch_id,$orders_info['cash_fee']/100,$orders_info['transaction_id']); $this->writeLogs(RUNTIME_PATH.'Logs/','proOrders',"\r\n-------------------".date('Y-m-d H:i:s')."微信支付數據處理結果---------\r\n---響應數據:".json_encode($data_handle)."\r\n------------\r\n"); //支付方式入庫 $pay_data = array( 'orders_id' => $data_handle['orders_id'], //訂單編號 'branch_id' => (int)$branch_id, // 店鋪 ID 'pay_sn' => $orders_info['transaction_id'], // 支付 SN 'pay_total' => sprintf("%.2f",$orders_info['cash_fee']/100), // 支付金額 'pay_type' => 1, // 支付類型 'table_id' => $table_id, // 桌臺ID ); //添加副表 $pay_sn = $orders_model->add_orders_pay_sn($pay_data); $pay_state = $data_handle['state']; if($pay_state == 1){ //完成訂單 //完成訂單後,沒有確認的訂單也所有清空 add yangzl $del_redis_orders = $orders_model->del_redis_orders_p($branch_id, $table_id); if (!$del_redis_orders){ log::write( "現金訂單完成後收尾".$table_id); } //設置狀態 $table_model = new TablesModel(); $state = $table_model->set_table_state($table_id, $branch_id, 4); } // 服務員下單一對一推送 $table_base = $table_model->get_table_by_id($table_id,$branch_id); $table_title = $table_base['title']; Push::app_push_waiter_checkout($table_id, $table_title, '1'); exit(); }else{ //支付失敗 log::write( "支付訂單號數據支付失敗::支付訂單號".$orders_info['transaction_id']); exit(); } }else{ log::write( "支付訂單號數據已處理".$orders_info['transaction_id']); $this->returnXml(); exit(); } } /**********寫入日誌方法***********/ /** * 日誌記錄 * @param $path string 日誌文件目錄 * @param $file string 日誌文件名,不包含後綴 * @param $content string 記錄內容 * @param @author yangzl * @return void **/ public function writeLogs($path,$file,$content,$more=true){ $newpath = ''; if (!file_exists($path)) { mkdir ($path); @chmod ($path, 0777 ); } if($more){ $newpath .= $path.$file.@date('Y-m-d').".log"; }else{ $newpath .= $path.$file.".log"; } $content .="\r\n"."----------------------------------------------------------------------------------------------------------------"."\r\n"; $this->write_file($newpath,$content,"a+"); } /** * 寫內容 * @param $filename string 日誌文件名 * @param $data string 記錄內容 * @param $method * @author yanzl **/ private function write_file($filename,$data,$method="rb+",$iflock=1){ @touch($filename); $handle=@fopen($filename,$method); if($iflock){ @flock($handle,LOCK_EX); } @fputs($handle,$data); if($method=="rb+") @ftruncate($handle,strlen($data)); @fclose($handle); @chmod($filename,0777); if( is_writable($filename) ){ return 1; }else{ return 0; } } } ?>