Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ErrorException: Array to string conversion in /vendor/overtrue/wechat/src/Payment/Notify/Handler.php:196 #1485

Closed
ahu opened this issue Mar 7, 2019 · 11 comments

Comments

@ahu
Copy link

ahu commented Mar 7, 2019

我用的环境

CentOS 7.4

PHP 版本:7.1.26
overtrue/wechat 版本:4.1.19
是否使用了框架?框架名称:lumen

问题及现象

问题现象

打开lumen的log监控,当有支付完成后,过一会(应该是接收到来自微信的回调了)会看到如下报错信息

ErrorException: Array to string conversion in /vendor/overtrue/wechat/src/Payment/Notify/Handler.php:196

必要的代码段

[2019-03-07 18:11:14] local.ERROR: ErrorException: Array to string conversion in 【工程目录】/vendor/overtrue/wechat/src/Payment/Notify/Handler.php:196
Stack trace:
#0 [internal function]: Laravel\Lumen\Application->Laravel\Lumen\Concerns{closure}(8, 'Array to string...', '【工程目录】...', 196, Array)
#1 【工程目录】/vendor/overtrue/wechat/src/Payment/Notify/Handler.php(196): strval(Array)
#2 【工程目录】/vendor/overtrue/wechat/src/Payment/Notify/Paid.php(28): EasyWeChat\Payment\Notify\Handler->strict(Array)
#3 【工程目录】/vendor/overtrue/wechat/src/Payment/Application.php(115): EasyWeChat\Payment\Notify\Paid->handle(Object(Closure))
#4 【工程目录】/app/Http/Controllers/WechatPayController.php(552): EasyWeChat\Payment\Application->handlePaidNotify(Object(Closure))
#5 [internal function]: App\Http\Controllers\WechatPayController->notifyUrl(Object(Dingo\Api\Http\Request))
#6 【工程目录】/vendor/illuminate/container/BoundMethod.php(29): call_user_func_array(Array, Array)
#7 【工程目录】/vendor/illuminate/container/BoundMethod.php(87): Illuminate\Container\BoundMethod::Illuminate\Container{closure}()
#8 【工程目录】/vendor/illuminate/container/BoundMethod.php(31): Illuminate\Container\BoundMethod::callBoundMethod(Object(Laravel\Lumen\Application), Array, Object(Closure))
#9 【工程目录】/vendor/illuminate/container/Container.php(564): Illuminate\Container\BoundMethod::call(Object(Laravel\Lumen\Application), Array, Array, NULL)
#10 【工程目录】/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(373): Illuminate\Container\Container->call(Array, Array)
#11 【工程目录】/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(339): Laravel\Lumen\Application->callControllerCallable(Array, Array)
#12 【工程目录】/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(313): Laravel\Lumen\Application->callLumenController(Object(App\Http\Controllers\WechatPayController), 'notifyUrl', Array)
#13 【工程目录】/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(275): Laravel\Lumen\Application->callControllerAction(Array)
#14 【工程目录】/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(255): Laravel\Lumen\Application->callActionOnArrayBasedRoute(Array)
#15 [internal function]: Laravel\Lumen\Application->Laravel\Lumen\Concerns{closure}(Object(Dingo\Api\Http\Request))
#16 【工程目录】/vendor/laravel/lumen-framework/src/Routing/Pipeline.php(52): call_user_func(Object(Closure), Object(Dingo\Api\Http\Request))
#17 【工程目录】/vendor/dingo/api/src/Http/Middleware/PrepareController.php(45): Laravel\Lumen\Routing\Pipeline->Laravel\Lumen\Routing{closure}(Object(Dingo\Api\Http\Request))
#18 【工程目录】/vendor/illuminate/pipeline/Pipeline.php(151): Dingo\Api\Http\Middleware\PrepareController->handle(Object(Dingo\Api\Http\Request), Object(Closure))
#19 [internal function]: Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Dingo\Api\Http\Request))
#20 【工程目录】/vendor/laravel/lumen-framework/src/Routing/Pipeline.php(32): call_user_func(Object(Closure), Object(Dingo\Api\Http\Request))
#21 【工程目录】/vendor/illuminate/pipeline/Pipeline.php(104): Laravel\Lumen\Routing\Pipeline->Laravel\Lumen\Routing{closure}(Object(Dingo\Api\Http\Request))
#22 【工程目录】/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(410): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#23 【工程目录】/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(256): Laravel\Lumen\Application->sendThroughPipeline(Array, Object(Closure))
#24 【工程目录】/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(230): Laravel\Lumen\Application->handleFoundRoute(Array)
#25 【工程目录】/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(164): Laravel\Lumen\Application->handleDispatcherResponse(Array)
#26 【工程目录】/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(413): Laravel\Lumen\Application->Laravel\Lumen\Concerns{closure}()
#27 【工程目录】/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(166): Laravel\Lumen\Application->sendThroughPipeline(Array, Object(Closure))
#28 【工程目录】/vendor/dingo/api/src/Routing/Adapter/Lumen.php(103): Laravel\Lumen\Application->dispatch(Object(Dingo\Api\Http\Request))
#29 【工程目录】/vendor/dingo/api/src/Routing/Router.php(513): Dingo\Api\Routing\Adapter\Lumen->dispatch(Object(Dingo\Api\Http\Request), 'v1')
#30 【工程目录】/vendor/dingo/api/src/Http/Middleware/Request.php(126): Dingo\Api\Routing\Router->dispatch(Object(Dingo\Api\Http\Request))
#31 【工程目录】/vendor/illuminate/pipeline/Pipeline.php(116): Dingo\Api\Http\Middleware\Request->Dingo\Api\Http\Middleware{closure}(Object(Dingo\Api\Http\Request))
#32 【工程目录】/vendor/illuminate/pipeline/Pipeline.php(104): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Dingo\Api\Http\Request))
#33 【工程目录】/vendor/dingo/api/src/Http/Middleware/Request.php(127): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#34 【工程目录】/vendor/dingo/api/src/Http/Middleware/Request.php(103): Dingo\Api\Http\Middleware\Request->sendRequestThroughRouter(Object(Dingo\Api\Http\Request))
#35 【工程目录】/vendor/illuminate/pipeline/Pipeline.php(151): Dingo\Api\Http\Middleware\Request->handle(Object(Dingo\Api\Http\Request), Object(Closure))
#36 [internal function]: Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request))
#37 【工程目录】/vendor/laravel/lumen-framework/src/Routing/Pipeline.php(32): call_user_func(Object(Closure), Object(Illuminate\Http\Request))
#38 【工程目录】/vendor/illuminate/pipeline/Pipeline.php(104): Laravel\Lumen\Routing\Pipeline->Laravel\Lumen\Routing{closure}(Object(Illuminate\Http\Request))
#39 【工程目录】/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(410): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#40 【工程目录】/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(166): Laravel\Lumen\Application->sendThroughPipeline(Array, Object(Closure))
#41 【工程目录】/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(107): Laravel\Lumen\Application->dispatch(NULL)
#42 【工程目录】/public/index.php(28): Laravel\Lumen\Application->run()
#43 {main} {"exception":"[object] (ErrorException(code: 0): Array to string conversion at 【工程目录】/vendor/overtrue/wechat/src/Payment/Notify/Handler.php:196)

@overtrue
Copy link
Collaborator

你的通知处理逻辑的代码贴一下

@ahu
Copy link
Author

ahu commented Apr 11, 2019

@overtrue

/**
 * 处理微信支付回调
 */
public function notifyUrl(Request $request)
{
    $app         = Config::get('wechat.default');
    $payment     = Factory::payment($app);

    $response = $payment->handlePaidNotify(function ($result, $fail) {
        //响应微信回调
        return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
        exit();
    });
}

@ahu
Copy link
Author

ahu commented Apr 11, 2019

@overtrue 我觉得 overtrue/wechat/src/Payment/Notify/Handler.php:196 的strval 改为json_encode好点

@overtrue
Copy link
Collaborator

理由是什么呢?

@ahu
Copy link
Author

ahu commented Apr 12, 2019

😁理由就是现在我的项目里一有人付款服务器接收到微信支付回调就会报我上述的这个错误,我改为json_encode就没这个报错了。你用strval的目的就是为了保证输出的是一个字符串,但如果原始内容是数组就会有上述报错,json_encode一样可以把输入内容转为字符串,如果输入内容是数组也 ok 的

@overtrue
Copy link
Collaborator

overtrue commented Apr 12, 2019 via email

@ahu
Copy link
Author

ahu commented Apr 12, 2019

不是我返回的,微信支付回调是微信post过来的信息。
核心代码片段在上面(隐去的细节是我们接收到回调后进行数据处理),我只是使用了一下EasyWeChat的handlePaidNotify方法而已。是不是微信支付官方接口变了?

@almas1992
Copy link
Contributor

不是我返回的,微信支付回调是微信post过来的信息。
核心代码片段在上面(隐去的细节是我们接收到回调后进行数据处理),我只是使用了一下EasyWeChat的handlePaidNotify方法而已。是不是微信支付官方接口变了?

 /**
     * @param mixed $result
     */
    protected function strict($result)
    {
        if (true !== $result && is_null($this->fail)) {
            $this->fail(strval($result));
        }
    }

这里的 $result 是你的闭包函数返回的数据,不是 微信post过来的信息

@ahu
Copy link
Author

ahu commented Apr 12, 2019

@almas1992 这个$result在官网文档示例里是$message ,详见https://www.easywechat.com/docs/4.1/payment/notify 的代码示例,其中的
if ($message['return_code'] === 'SUCCESS') { // return_code 表示通信状态,不代表支付状态
明确表明了$message是来自微信的返回数组,做过微信支付的应该都清楚

@almas1992
Copy link
Contributor

almas1992 commented Apr 12, 2019

@almas1992 这个$result在官网文档示例里是$message ,详见https://www.easywechat.com/docs/4.1/payment/notify 的代码示例,其中的
if ($message['return_code'] === 'SUCCESS') { // return_code 表示通信状态,不代表支付状态
明确表明了$message是来自微信的返回数组,做过微信支付的应该都清楚

$response = $payment->handlePaidNotify(function ($result, $fail) {
        //响应微信回调
        return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
        exit();
    });

你这里调用的 $payment->handlePaidNotify() 方法源码是

 /**
     * @param \Closure $closure
     *
     * @return \Symfony\Component\HttpFoundation\Response
     *
     * @throws \EasyWeChat\Kernel\Exceptions\Exception
     */
    public function handle(Closure $closure)
    {
        $this->strict(
            \call_user_func($closure, $this->getMessage(), [$this, 'fail'])
        );
        return $this->toResponse();
    }

我的理解是该方法把微信返回的数据和一个fail方法当参数传到你的闭包函数中,再把你返回的数据传入 $this->strict()中处理

/**
     * @param mixed $result
     */
    protected function strict($result)
    {
        if (true !== $result && is_null($this->fail)) {
            $this->fail(strval($result));
        }
    }

难道该函数中 $result 不是你闭包函数中返回的结果?

明确表明了$message是来自微信的返回数组,做过微信支付的应该都清楚

源码表明 微信post过来的信息是 $message ,而 strval($result) 中的 $result 是你返回的数据, 写过PHP的应该都清楚

@ahu
Copy link
Author

ahu commented Apr 12, 2019

@almas1992 一语惊醒梦中人,我去看了一下easywechat源码,大概知道问题所在了,感谢!
@overtrue 抱歉带来干扰!误会你说的'官方'了,我以为是说微信支付...[捂脸] 原来你说的是easywechat

我再次表示:我对那股神秘的力量太一无所知了!就让这条issue留着警醒后人吧~

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants