微信支付结果通知接受不到传回来的xml

微信支付成功后用js跳转到之前设置的notify_url地址,我用file_get_contents('php://input')无法获取微信传回来的通知xml;

我也查了很多资料了,以下几点说明:
1.我用的是yii2的php框架
2.我用file_get_contents($_SERVER['DOCUMENT_ROOT'].'/test.xml')可以正常获取解析测试的xml文件
3.设置的notify_url地址:‘http://*.com/wxpay/payres/’,没有带任何参数而且访问没有问题
4.支付成功后我有查过nginx的log,微信服务器有post过来
5.下边结果通知action里边验证签名什么的代码我都暂时给去掉了,现在xml都获取不到

wxpay/index - 发起支付的ajax
(我之前以为支付成功后微信那边会自动跳转到notify_url地址,后来不行,在网上搜了下改成了window.location.href跳转,我不知道这种方式是否会有问题)

success: function (res) {
    $("#recharge_btn").button('reset');
    if (res.status == 200) {
        WeixinJSBridge.invoke(
            'getBrandWCPayRequest',res.jsApiParameters,
            function(res){
                if(res.err_msg == "get_brand_wcpay_request:ok" ) {
                    // 支付成功后的回调函数
                   window.location.href="http://***.com/wxpay/payres/";
                }
                
            }
        );
    }else{
        $("#my-alert").modal("open").find(".am-modal-bd").html(res.msg);
    }
},

下单的配置

 //②、统一下单
        //$input = new WxPayUnifiedOrder();
        $input = new WxPayUnifiedOrder();
        $input->SetBody($body);    //商品描述
        $input->SetAttach($myattach); //自定义参数(邀请码)
        $input->SetDevice_info("WEB"); //微信支付分配的终端设备号,商户自定义
        $input->SetOut_trade_no(WxPayConfig::MCHID . date("YmdHis"));  //商户系统内部的订单号,32个字符内、可包含字母, 其他说明见商户订单号
        $input->SetTotal_fee($paymoney); //订单总金额,单位为分
        $input->SetTime_start(date("YmdHis")); //交易起始时间
        $input->SetTime_expire(date("YmdHis", time() + 600));  //交易结束时间
        $input->SetGoods_tag("mytag");  //订单优惠标记,使用代金券或立减优惠功能时需要的参数
        $input->SetNotify_url("http://***.com/wxpay/payres/");
        $input->SetTrade_type("JSAPI");
        $input->SetOpenid($openId);
        $order = WxPayApi::unifiedOrder($input);

结果通知的action:

    /**
     * 充值结果通知
     * @return string
     */
    public function actionPayres()
    {
        $xml = file_get_contents('php://input');
        libxml_disable_entity_loader(true);
        $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
//        echo "<pre>";
//        print_r($data);
//        echo "</pre>";
        return $this->render('payres',[
            'resmsg' => $data['transaction_id'],
        ]);
    }
阅读 7.8k
6 个回答

楼主对notify_url的理解出现了偏差,支付回调是第三方根据你调用支付传递的notify_url地址进行请求调用,并且附带参数过来了,你需要做的就是提供接口,在接口这边写好你的业务逻辑,而不是你js跳到notify_url。获取第三方发起的请求参数,微信可以用file_get_contents('php://input'),当然是在你接口那边设置,不建议使用HTTP_RAW_POST_DATA,这个在php7中已经被放弃了。

首先,楼主的notify_url的理解错误。
notify_url称为支付回调,这个回调是给腾讯服务器通知支付结果,你方服务器完成业务逻辑用的。
而非你上面所讲的,你用js跳转notify_url,这个notify_url非你访问的。

public function noticeFirst() {

        Vendor('WXPAYS.lib.WxPayPubHelper');
        $notify = new \Notify_pub();

        //存储微信的回调
        $xml = $GLOBALS['HTTP_RAW_POST_DATA'];
        $notify->saveData($xml);
        $arr = $notify->data;


        //验证签名,并回应微信。
        //对后台通知交互时,如果微信收到商户的应答不是成功或超时,微信认为通知失败,
        //微信会通过一定的策略(如30分钟共8次)定期重新发起通知,
        //尽可能提高通知的成功率,但微信不保证通知最终能成功。
        $wxpay_config = array(
            'APPID' => '',
            'MCHID' => '',
            'KEY' => '',
            'APPSECRET' => ''
        );
        if ($notify->checkSign($wxpay_config) === FALSE) {
            $notify->setReturnParameter("return_code", "FAIL"); //返回状态码
            $notify->setReturnParameter("return_msg", "签名失败"); //返回信息
        } else {
            $notify->setReturnParameter("return_code", "SUCCESS"); //设置返回码
        }
        $returnXml = $notify->returnXml();
        echo $returnXml;

        //==商户根据实际情况设置相应的处理流程,此处仅作举例=======
        if ($notify->checkSign($wxpay_config) === TRUE) {

            if ($arr["return_code"] == "FAIL") {
                
            } elseif ($arr["result_code"] == "FAIL") {
                
            } else {

                $info = M('order')->where(array('order_sn' => $arr['out_trade_no']))->find();

                if (!$info) {
                    exit('订单信息有误');
                }
                /* 修改订单状态 */
                $data['status'] = 1;
                $time_end = substr($arr['time_end'], 0, 4) . '-' . substr($arr['time_end'], 4, 2) . '-' . substr($arr['time_end'], 6, 2) . ' ' . substr($arr['time_end'], 8, 2) . ':' . substr($arr['time_end'], 10, 2). ':' . substr($arr['time_end'], 12, 2);
                $data['pay_time'] = strtotime($time_end);
                M('order')->where(array('order_id' => $info['order_id']))->save($data);
                $total_fee=$arr['total_fee'];
                       
                /* 添加支付流水 */
                $_data['appid'] = $arr['appid'];
                $_data['bank_type'] = $arr['bank_type'];
                $_data['cash_fee'] = $arr['cash_fee'];
                $_data['fee_type'] = $arr['fee_type'];
                $_data['is_subscribe'] = $arr['is_subscribe'];
                $_data['mch_id'] = $arr['mch_id'];
                $_data['openid'] = $arr['openid'];
                $_data['out_trade_no'] = $arr['out_trade_no'];
                $_data['result_code'] = $arr['result_code'];
                $_data['return_code'] = $arr['result_code'];
                $_data['total_fee'] = $total_fee;
                $_data['trade_type'] = $arr['trade_type'];
                $_data['transaction_id'] = $arr['transaction_id'];
                $_data['nonce_str'] = $arr['nonce_str'];
                $_data['sign'] = $arr['sign'];
                $_data['time_end'] = $arr['time_end'];
                $pay_flow_id=M('payment_flow')->add($_data);
                
                /* 添加财务流水 */
                //订单ID
                $_trans_data['order_id']=$info['order_id'];
                //会员ID
                $_trans_data['user_id']=$info['user_id'];
                //交易流水号
                $_trans_data['flow_id']=$pay_flow_id;
                //交易类型
                $_trans_data['trans_type']='1';
                //交易渠道
                $_trans_data['trans_channel']='1';
                $_trans_data['amount']=$total_fee*0.01;
                $_trans_data['add_time']=time();
                M('trans_flow')->add($_trans_data);
               
            }

            //商户自行增加处理流程,
            //例如:更新订单状态
            //例如:数据库操作
            //例如:推送支付完成信息
        }

如果你用jsapi发起支付,支付结果给的支付成功,一般的是支付的步骤完成,全部完成一般要一秒左右才知道,所以只要接口返回ok,直接跳转到订单结果,不管有没有成功。

<script type="text/javascript">
    //调用微信JS api 支付
    function jsApiCall()
    {
        WeixinJSBridge.invoke(
            'getBrandWCPayRequest',
                        {$jsApiParameters},
            function(res){
                            if(res.err_msg == "get_brand_wcpay_request:ok"){  
                    alert("支付成功!");  
//                    window.location.href="{:U('Index/orderDetail',array('order_sn'=>$info['order_sn']))}"; 
                     window.location.href="{:U('Order/orderDetail',array('order_sn'=>$info['order_sn']))}"; 
                
                    }else if(res.err_msg == "get_brand_wcpay_request:cancel"){  
                 
                     window.location.href="{:U('Order/orderDetail',array('order_sn'=>$info['order_sn']))}"; 
                 
                    
                    }else{  
                       // alert("支付失败!");  
                        window.location.href="{:U('Order/orderDetail',array('order_sn'=>$info['order_sn']))}"; 
                    }  
    
                
            }
        );
    }

    function callpay()
    {
        if (typeof WeixinJSBridge == "undefined"){
            if( document.addEventListener ){
                document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);
            }else if (document.attachEvent){
                document.attachEvent('WeixinJSBridgeReady', jsApiCall); 
                document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
            }
        }else{
            jsApiCall();
        }
    }
    </script>

http://*.com/wxpay/payres/这个地址去接收商品信息就行了
不过有点特殊的是,例如laravel里这样也收不到,就是框架捣的鬼,要查查看,有些框架自身帮你获取了,你得用它的方法

新手上路,请多包涵

楼上说的基本的都点中了,楼主对notify_url理解有误,notify_url只是腾讯在完成支付的操作后会请求的一个地址

$input->SetNotify_url("http://*.com/wxpay/payres/"); 这里设置的是异步回调接口,只进行业务逻辑处理不显示在前端,接口中编写支付成功后的数据处理,可以在接口里面做一个日志存储,就知道是不是调用了。

window.location.href="http://*.com/wxpay/payres/"; 这个是支付成功后,跳转的页面,和Notify_url 是不一样的

当然可以作为你的支付结果跳转页面地址。

如果你把你的微信支付异步通知URL(notify_url)和微信同步跳转url设定为一样的时候,那么从两种状态过来的时候所做的处理也就不一样。
1、作为支付结果同步跳转url的时候(这个指的是js里跳转的url),只是作为一个支付后跳转的地址而已,具体的支付结果要根据异步通知(notify_url)来确定
2、作为异步通知地址(notify_url),这里微信会发送真实的交易支付结果回来,把这个数据作为订单支付结果的真实依据

同一地址作为不同状态的调用时所做的业务逻辑,只要题主设定好就没问题了。比如说当有post数据的时候就是微信异步通知,没有post数据的时候,只是单纯的作为一个地址或者页面来处理。

题主说查看nginx日志有post数据过来,但是并不代表代码正确执行了。建议楼主在对应的方法中手写记录日志操作,把数据记录在文件里,再进行调试。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题