微信支付回调验证签名处理
微信支付回调验证签名:一定要验证签名,可能不造成伪造数据,或者数据库造到灌水;
<?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; } } } ?>