欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

微信支付回调验证签名处理

程序员文章站 2022-09-14 18:44:57
微信支付回调验证签名:一定要验证签名,可能不造成伪造数据,或者数据库造到灌水; ......

微信支付回调验证签名:一定要验证签名,可能不造成伪造数据,或者数据库造到灌水;

<?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;
        }
    }
}


 ?>