webman中使用WxPayApi(3.0.10)不能响应回调的解决办法

jones

问题描述:使用微信支付API,如下图
微信支付API 3.0.10
在完成支付后,微信后台向我的服务器发送请求,以通知支付结果。具体回调地址是在WxPayConfig.php文件中进行配置,具体可参见微信支付的官方文档,这里只讲回调不能响的问题,以及如何解决的。
响应回调只需要在设置好的回调方法中写如下三行:

$config = new WxPayConfig();
$notify = new PayNotifyCallBack();
$notify->Handle($config, true);

由于微信支付回调请求发来的是raw数据,所以需要对该WxPayApi.php文件稍作修改;
修改前:

/**
     * 
     * 支付结果通用通知
     * @param function $callback
     * 直接回调函数使用方法: notify(you_function);
     * 回调类成员函数方法:notify(array($this, you_function));
     * $callback  原型为:function function_name($data){}
     */
    public static function notify($config, $callback, &$msg)
    {
        //获取通知的数据
        $xml = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : file_get_contents("php://input");
        if (empty($xml)) {      //在webman里,前面这段代码获取不到数据,无法做出响应
            # 如果没有数据,直接返回失败
            return false;
        }

        //如果返回成功则验证签名
        try {
            $result = WxPayNotifyResults::Init($config, $xml);
        } catch (WxPayException $e){
            $msg = $e->errorMessage();
            return false;
        }

        return call_user_func($callback, $result);
    }

修改后:

public static function notify($config, $callback, &$msg)
    {
        $xml = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : file_get_contents("php://input");

        if (empty($xml)) {
            # 如果没有数据,直接返回失败
            $xml = request()->rawBody();            //用rawBody()方法获取回调数据
            if (empty($xml)) {                              //增加判断
                return false;
            }
        }
        //如果返回成功则验证签名
        try {
            $result = WxPayNotifyResults::Init($config, $xml);
        } catch (WxPayException $e){
            $msg = $e->errorMessage();
            return false;
        }

        return call_user_func($callback, $result);
    }

这样就能接收到回调数据了
接下来修改WxPayNotify.php的Handle、ReplyNotify两个方法
修改handle前:

/**
     * 
     * 回调入口
     * @param bool $needSign  是否需要签名返回
     */
    final public function Handle($config, $needSign = true)
    {
        $this->config = $config;
        $msg = "OK";
        //当返回false的时候,表示notify中调用NotifyCallBack回调失败获取签名校验失败,此时直接回复失败
        $result = WxpayApi::notify($config, array($this, 'NotifyCallBack'), $msg);
        if($result == false){
            $this->SetReturn_code("FAIL");
            $this->SetReturn_msg($msg);
            $this->ReplyNotify(false);
            return;
        } else {
            //该分支在成功回调到NotifyCallBack方法,处理完成之后流程
            $this->SetReturn_code("SUCCESS");
            $this->SetReturn_msg("OK");
        }
        $this->ReplyNotify($needSign); 
    }

修改handle后:

final public function Handle($config, $needSign = true)
    {
        $this->config = $config;
        $msg = "OK";
        //当返回false的时候,表示notify中调用NotifyCallBack回调失败获取签名校验失败,此时直接回复失败
        $result = WxpayApi::notify($config, array($this, 'NotifyCallBack'), $msg);
        if($result == false){
            $this->SetReturn_code("FAIL");
            $this->SetReturn_msg($msg);
            $this->ReplyNotify(false);
            return;
        } else {
            //该分支在成功回调到NotifyCallBack方法,处理完成之后流程
            $this->SetReturn_code("SUCCESS");
            $this->SetReturn_msg("OK");
        }
        return $this->ReplyNotify($needSign); //前面加了return 
    }

修改ReplyNotify前:

    private function ReplyNotify($needSign = true)
    {
        //如果需要签名
        if($needSign == true && 
            $this->GetReturn_code() == "SUCCESS")
        {
            $this->SetSign($this->config);
        }

        $xml = $this->ToXml();
        $this->LogAfterProcess($xml);

        WxpayApi::replyNotify($xml);
    }

修改ReplyNotify后:

private function ReplyNotify($needSign = true)
    {
        //如果需要签名
        if($needSign == true && 
            $this->GetReturn_code() == "SUCCESS")
        {
            $this->SetSign($this->config);
        }

        $xml = $this->ToXml();
        $this->LogAfterProcess($xml);

        return WxpayApi::replyNotify($xml); //在前面加了return
    }

修改WxPayApi.php
修改前

/**
     * 直接输出xml
     * @param string $xml
     */
    public static function replyNotify($xml)
    {
        echo $xml;
    }

修改后

public static function replyNotify($xml)
    {
        return $xml;        //把echo 改为 return 
    }

最后,还要把自己的回调方法里的三行代码修改一下:
修改前:

$config = new WxPayConfig();
$notify = new PayNotifyCallBack();
$notify->Handle($config, true);

修改后:

$config = new WxPayConfig();
$notify = new PayNotifyCallBack();
return xml($notify->Handle($config, true)); //加了xml助手函数并且return其返回结果

至此,就笨拙地解决了不能响应回调的问题,但还没有找到为什么webman不能在response中输出该SDK中的echo 内容(即字符串格式的$xml)的原因。如有知道的请指告知,谢谢!


本方法的思路是:把不能直接echo 到 response 中的数据,通过若干个 return 一直返回到 响应支付回调的那个方法里,并在响应给客户端之前先调用了xml助手函数(生成其需要的XML格式数据)。


有热心人提到微信支付的v3版本已经改为了json格式,但由于本API使用的是XML传输,为减少代码修改量,暂未替换成v3版本的SDK.
上述内容有错误、疏漏之处,欢迎指出

949 0 2
0个评论

jones

214
积分
0
获赞数
0
粉丝数
2020-10-05 加入
🔝