overtrue / laravel-wechat

微信 SDK for Laravel, 基于 overtrue/wechat
MIT License
2.87k stars 500 forks source link

$payment->order->unify returning empty array #236

Closed gilles6 closed 6 years ago

gilles6 commented 6 years ago

I'm getting an empty array when my WeChatController is called, not even an error message, and the notify() is not called. What's wrong my code ?

<?php

namespace App\Http\Controllers;

use EasyWeChat;
use Log;

class WeChatController extends Controller
{
    /**
     * 处理微信的请求消息
     *
     * @return string
     */
    public function serve()
    {

        $payment = EasyWeChat::payment('default');

        $result = $payment->order->unify([
            'trade_type' => 'JSAPI',
            'body' => 'MY BODY',
            'detail' => 'MY DETAILS',
            'out_trade_no' => 'MYERPORDERID12345680',
            'total_fee' => 1.01,
            'spbill_create_ip' => '120.76.101.172',
            'openid' => 'wxd37384b6a45b69ac',
        ]);

        Log::info($result);

        return $result;
    }

    public function notify($r)
    {
        Log::info('!!! Payment notification !!!');
        Log::info($r);
    }
}

web.php

Route::any('/wechat', 'WeChatController@serve');
Route::any('/payments/wechat-notify', 'WeChatController@notify');
overtrue commented 6 years ago
$result = $payment->order->unify([
            'trade_type' => 'JSAPI',
            'body' => 'MY BODY',
            'detail' => 'MY DETAILS',
            'out_trade_no' => 'MYERPORDERID12345680',
            'total_fee' => 1.01,
            'spbill_create_ip' => '120.76.101.172',
            'openid' => 'wxd37384b6a45b69ac',
            'notify_url' => url('xxxxx') // <------ here
        ]);
gilles6 commented 6 years ago

Thanks for your fast answer!

I have add 'notify_url' => url('http://my.website.com/payments/wechat-notify') but I still get an empty array and the notify_url is not called. What else could be wrong ?

overtrue commented 6 years ago
  1. 查看 easywechat 日志,看 unify 返回的结果
  2. 检查 unify 传入的数组值,是否有不正确的结果
  3. 检查 nginx access_log ,看微信的回调是否真的调用
gilles6 commented 6 years ago
  1. 用浏览器打开my.website.com/wechat的时候,wechat.log里面没什么新的日志。 $ tail -f storage/logs/wechat.log

  2. unify 传入的数组值怎么检查结果?

  3. 我用的Apache日志里没看到什么异常的。

另外,notify_url我也不确定要用下面的哪个,放在我的Controller里面好,还是放在config/wechat.php好?

WeChatController.php

    public function serve()
    {
        Log::info('request arrived.');

        $payment = EasyWeChat::payment('default');

        $result = $payment->order->unify([
            'trade_type' => 'JSAPI',
            'body' => 'MY BODY',
            'detail' => 'MY DETAILS',
            'out_trade_no' => 'MYERPORDERID12345680',
            'total_fee' => 1.01,
            'spbill_create_ip' => '120.76.101.172',
            'openid' => 'wxd37384b6a45b69ac',
            // 'notify_url' => url('https://pay.weixin.qq.com/wxpay/pay.action')
            'notify_url' => url('http://my.website.com/payments/wechat-notify')
        ]);

        Log::info($result);

        return $result;
    }

config/wechat.php

return [
    ...
    'payment' => [
        'default' => [
            'sandbox' => env('WECHAT_PAYMENT_SANDBOX', true),
            'app_id' => env('WECHAT_PAYMENT_APPID', 'wxd373c'),
            'mch_id' => env('WECHAT_PAYMENT_MCH_ID', '12341'),
            'key' => env('WECHAT_PAYMENT_KEY', 'H8H06Z721qs345U6q62c786433KCC68D'),
            'cert_path' => env('WECHAT_PAYMENT_CERT_PATH', '/Users/me/code/wechat_cert/apiclient_cert.pem'),
            'key_path' => env('WECHAT_PAYMENT_KEY_PATH', '/Users/me/code/wechat_cert/apiclient_key.pem'),
            // 'notify_url' => env('http://my.website.com/payments/wechat-notify'),
            // 'notify_url' => env('https://pay.weixin.qq.com/wxpay/pay.action'),
        ],
    ],
almas1992 commented 6 years ago

检查一下 app/Http/Middleware/VerifyCsrfToken.php protected $except = [ ],有没除掉你的 notify 路由;

overtrue commented 6 years ago

@devondahon 请不要直接粘贴敏感信息

overtrue commented 6 years ago

@devondahon 你是在服务器上调试的吧?不是本地吧

gilles6 commented 6 years ago

@almas1992

$ cat app/Http/Middleware/VerifyCsrfToken.php
<?php                                                                                                                                                                                

namespace App\Http\Middleware;

use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;

class VerifyCsrfToken extends Middleware
{
    /**
     * The URIs that should be excluded from CSRF verification.
     *
     * @var array
     */
    protected $except = [
        //
        'wechat',
    ];
}

@overtrue 没放敏感信息,信息都是假的。我是在本地编码然后git push之后在服务器上面看结果。

另外,app_id和openid写的是一样。 我是在这里找到了app_id: pay.weixin.qq.com > 营销中心 > 支付后配置 > 发起支付的appid 这个网站上没找到openid。

overtrue commented 6 years ago
  1. 'wechat' 改成 'wechat/*'
  2. 'openid' 是当前订单的用户的 openid 这个可不是 appid....
gilles6 commented 6 years ago
  1. 把'wechat' 改成 'wechat/*'之后,数组还是空的,notify也没有反应。
  2. 'appid'在pay.weixin.qq.com里还是找不到,途径是什么?
overtrue commented 6 years ago

appid 是公众号 id...

gilles6 commented 6 years ago

说错了,不好意思,我的意思是openid在pay.weixin.qq.com里找不到。

overtrue commented 6 years ago

@devondahon openid 当然在那里找不到啊,那明明是公众号的东西

gilles6 commented 6 years ago

Sorry, my Chinese is limited.

Do I have to set the openid in $payment->order->unify([...]) and, if yes, where should I get it from ?

I made a request to your QQ group, it's maybe a better place to talk about my empty array problem before posting the solution here.

overtrue commented 6 years ago

You can get openid from wechat server push message FromUserName or OAuth login result.

gilles6 commented 6 years ago

What I need first is to display a payment QR code in the browser. Should this QR code be requested with EasyWechat ?

overtrue commented 6 years ago

normal pay (公众号支付)

https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_1

  1. oauth/server push message -> get user info (openid)
  2. create wechat order(unify) with openid -> build QR code
  3. user click -> wechat jssdk call payment api and complete pay.

Sacn pay (扫码支付)

https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_1

  1. create product scheme:
    $payment->scheme($productId) // $productId is your database product id

    weixin://wxpay/bizpayurl?xxxxxxx=xxxx

  2. create QR code using your favorite library with scheme result.

  3. user scan the QR

  4. wechat notify your server by the url your configured from pay.wx.qq.com admin panel. image

  5. handle the notify, you will get openid and product id from notify body. and create order by unify method. return the response.

  6. user completed pay.

  7. notify you the result.

So, you must be read the official docs and know the logic.

gilles6 commented 6 years ago

Thanks for the references.

Could you please provide some code examples ?

Like this one: https://hotexamples.com/examples/overtrue.wechat/Payment/-/php-payment-class-examples.html Bu this one seems to concern an older version of EasyWeChat. Most examples I found on Google are outdated unfortunately.

overtrue commented 6 years ago

@devondahon 对不起,也许你需要自己找身边中文熟悉的朋友帮忙你详细阅读理解微信官方的文档,我工作繁忙,没有时间帮忙哦。抱歉。

gilles6 commented 6 years ago

Nevermind. Thanks for your help!

gilles6 commented 6 years ago

@overtrue 我终于明白了!手机里打开公众号发消息的时候,服务器那边都有日志了。 非常感谢你耐心,也非常感谢你提供的这个工具!

overtrue commented 6 years ago

@devondahon 是的

overtrue commented 6 years ago

@devondahon 不客气