yansongda/pay 支付遇到的坑

最近做了一个微信公众号支付 , 使用的是laravel 8 框架 , 使用的是yansongda 2.0 版本,通过composer 下载( composer require yansongda/pay:~2 ),一切就绪后咋们就开始吧!

我遇到的坑就是回调路由无效,当时支付了很多笔,也支付成功了,但是设置的回调方法一点作用都没用,根本不走设置的回调路由这个方法,另外也在微信商户平台也设置过回调路由地址了,并且请求参数回调路由可以走的通,到底怎么回事呢,我们来看看:

下面是当时设置的路由(因为使用的是get方式所以接收不到xml数据):

这是我设置的回调地址:https://xxxxxx.com/api/wxpay/notify

路由设置

$router->get("api/wxpay/notify","LoginPaymentController@notifyCallback");//微信支付回调地址

然后看了日志目录地址(/storage/logs/lumen-2021-11-23.log) , 说接收不到xml数据导致的

[2021-11-23 10:24:27] local.ERROR: INVALID_ARGUMENT: Convert To Array Error! Invalid Xml! {"exception":"[object] (Yansongda\\Pay\\Exceptions\\InvalidArgumentException(code: 3): INVALID_ARGUMENT: Convert To Array Error! Invalid Xml! at /www/wwwroot/footballInfo/vendor/yansongda/pay/src/Gateways/Wechat/Support.php:306)
[stacktrace]
#0 /www/wwwroot/footballInfo/vendor/yansongda/pay/src/Gateways/Wechat.php(173): Yansongda\\Pay\\Gateways\\Wechat\\Support::fromXml('')
#1 /www/wwwroot/footballInfo/app/Http/Controllers/Api/Wxpay/LoginPaymentController.php(79): Yansongda\\Pay\\Gateways\\Wechat->verify()
#2 /www/wwwroot/footballInfo/vendor/illuminate/container/BoundMethod.php(36): App\\Http\\Controllers\\Api\\Wxpay\\LoginPaymentController->notifyCallback(Object(Laravel\\Lumen\\Http\\Request))
#3 /www/wwwroot/footballInfo/vendor/illuminate/container/Util.php(40): Illuminate\\Container\\BoundMethod::Illuminate\\Container\\{closure}()
#4 /www/wwwroot/footballInfo/vendor/illuminate/container/BoundMethod.php(93): Illuminate\\Container\\Util::unwrapIfClosure(Object(Closure))
#5 /www/wwwroot/footballInfo/vendor/illuminate/container/BoundMethod.php(37): Illuminate\\Container\\BoundMethod::callBoundMethod(Object(Laravel\\Lumen\\Application), Array, Object(Closure))
#6 /www/wwwroot/footballInfo/vendor/illuminate/container/Container.php(651): Illuminate\\Container\\BoundMethod::call(Object(Laravel\\Lumen\\Application), Array, Array, NULL)
#7 /www/wwwroot/footballInfo/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(389): Illuminate\\Container\\Container->call(Array, Array)
#8 /www/wwwroot/footballInfo/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(355): Laravel\\Lumen\\Application->callControllerCallable(Array, Array)
#9 /www/wwwroot/footballInfo/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(329): Laravel\\Lumen\\Application->callLumenController(Object(App\\Http\\Controllers\\Api\\Wxpay\\LoginPaymentController), 'notifyCallback', Array)
#10 /www/wwwroot/footballInfo/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(282): Laravel\\Lumen\\Application->callControllerAction(Array)
#11 /www/wwwroot/footballInfo/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(267): Laravel\\Lumen\\Application->callActionOnArrayBasedRoute(Array)
#12 /www/wwwroot/footballInfo/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(169): Laravel\\Lumen\\Application->handleFoundRoute(Array)
#13 /www/wwwroot/footballInfo/vendor/laravel/lumen-framework/src/Routing/Pipeline.php(48): Laravel\\Lumen\\Application->Laravel\\Lumen\\Concerns\\{closure}(Object(Laravel\\Lumen\\Http\\Request))
#14 /www/wwwroot/footballInfo/app/Http/Middleware/CorsMiddleware.php(31): Laravel\\Lumen\\Routing\\Pipeline->Laravel\\Lumen\\Routing\\{closure}(Object(Laravel\\Lumen\\Http\\Request))
#15 /www/wwwroot/footballInfo/vendor/illuminate/pipeline/Pipeline.php(167): App\\Http\\Middleware\\CorsMiddleware->handle(Object(Laravel\\Lumen\\Http\\Request), Object(Closure))
#16 /www/wwwroot/footballInfo/vendor/laravel/lumen-framework/src/Routing/Pipeline.php(30): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Laravel\\Lumen\\Http\\Request))
#17 /www/wwwroot/footballInfo/vendor/illuminate/pipeline/Pipeline.php(103): Laravel\\Lumen\\Routing\\Pipeline->Laravel\\Lumen\\Routing\\{closure}(Object(Laravel\\Lumen\\Http\\Request))
#18 /www/wwwroot/footballInfo/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(426): Illuminate\\Pipeline\\Pipeline->then(Object(Closure))
#19 /www/wwwroot/footballInfo/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(175): Laravel\\Lumen\\Application->sendThroughPipeline(Array, Object(Closure))
#20 /www/wwwroot/footballInfo/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(112): Laravel\\Lumen\\Application->dispatch(NULL)
#21 /www/wwwroot/footballInfo/public/index.php(28): Laravel\\Lumen\\Application->run()
#22 {main}
"} 

然后改为post请求方式就一切搞定了 

$router->post("api/wxpay/notify","LoginPaymentController@notifyCallback");//微信支付回调地址

use Yansongda\Pay\Pay; //引入包
   

public  $wechat = [];




 // 下单和唤醒微信支付
    public function wechatPay(Request $request)
    {   
        
         $this->wechat = ['appid'        => '', // APP APPID
        'app_id'       => 'wx3063dafs4fbc3a6f09e', // 公众号 APPID
        'miniapp_id'   => '', // 小程序 APPID
        'mch_id'       => '1162163841168',
        'key'          => '8E1F99E9F2E116AC98F029C71CE8155916E',
        'notify_url'   => 'https://aaaaaaaa.com/api/wxpay/notify',
        'cert_client'  => base_path('storage/cert/apiclient_cert.pem'), // optional, 退款,红包等情况时需要用到
        'cert_key'     => base_path('storage/cert/apiclient_key.pem'),// optional, 退款,红包等情况时需要用到
        'log' => [ 
            'file'     => storage_path('logs/wechat.log'),
            'level'    => 'debug', // 建议生产环境等级调整为 info,开发环境为 debug
            'type'     => 'single', // optional, 可选 daily.
            'max_file' => 30, // optional, 当 type 为 daily 时有效,默认 30 天
        ],
        'http' => [ 
            'timeout'         => 5.0,
            'connect_timeout' => 5.0,
        ],
        'mode'                => 'normal',];

        $user_id      = $request->user_id;
        $user_level   = $request->user_level;
        $price        = $request->price;
        $actual_price = $request->actual_price;
        $package_type = $request->package_type;
        $openid       = $request->openid;

        $config       = $this->wechat;
        $order_num    = date("YmdHis").rand(1,100000);

        $order = [
            'out_trade_no' => $order_num,
            'total_fee'    => $actual_price*100, // **单位:分**
            'body'         => 'vip'.$user_level.'购买',
            'openid'       => $openid,
        ];
        
        //获取唤醒微信支付参数    
        $result = Pay::wechat($config)->mp($order)->toarray();
        //打印 $result , 是以下参数
        //"appId": "wx0632daf4fbc36fasb",
		//"timeStamp": "11637571939",
		//"nonceStr": "0p2SOtmbt2objoJ5Za",
		//"package": "prepay_id=wx22170540055460b70225911e17fe3c0000",
		//"signType": "MD5",
		//"paySign": "1CE90AFE3EF33E5289AB880D1054C593"        

        // 生成订单
        $insert["user_id"]       = $user_id;
        $insert["order_num"]     = $order_num;
        $insert["recharge_type"] = 1;
        $insert["status"]        = 1;
        $insert["add_time"]      = date("Y-m-d H:i:s",time());
        $insert["goods_type"]    = $user_level;
        $insert["order_price"]   = $price;
        $insert["actual_price"]  = $actual_price;
        $insert["package_type"]  = $package_type;
        DB::table("order")->insert( $insert );

        writeLog('wechatPay', [
            'wechatPay' => $result,
            'order'     => $insert,
        ],true);

        //直接返回给前端,做到这步就可以唤醒微信输入支付密码支付页面了
        return $result;
    }
    
      
        
     
     // 微信支付回调
    public function notifyCallback(Request $request)
    { 
        $config = $this->wechat;
        $pay    = Pay::wechat($config);
       
        try {
            $data   = $pay->verify(); // 是的,验签就这么简单!
            //以下根据自己业务进行支付校验,更改订单状态什么的,看自己逻辑来
            $order  = Order::where('order_num', $data->out_trade_no)->get()->toarray();
            $order  = $order[0];

            if (!$order || $order['status'] != 1)  {
                writeLog('order_info', [
                    'msg' => "订单状态异常",
                    ],true);
                return;
            }
            if (($order['actual_price']) != $data->total_fee / 100) {
                writeLog('order_info', [
                    'msg' => "金额不匹配",
                    ],true);
                return;
            }
            //进行订单状态变更等支付成功操作
             // 更改订单状态
            $insert["user_id"]      = $user_info["id"];
            $insert["status"]       = 2;//改为已支付
            $insert["update_time"]  = date("Y-m-d H:i:s",time());
            $ins_id      = DB::table("order")->where("order_num",$param["order_num"])->update( $insert );

            return $pay->success();
            //好了做到这里微信公众号支付就搞定了
        } catch (Exception $e) {
            writeLog('order_info', [
                'error' => $e->getMessage(),
            ],true);
       }
    }   


版权声明:本文为weixin_44099311原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。