Laravel+easywechat 實現公眾號微信支付

_Mine發表於2019-12-02

Laravel+esaywechat實現公眾號微信支付

## 首先安裝easywechat包
laravel專案直接在終端跑以下命令:

composer require overtrue/wechat:~4.0

然後建立配置檔案:

php artisan vendor:publish --provider="Overtrue\LaravelWeChat\ServiceProvider"

建立配置檔案完成後會在你專案的config資料夾下生成一個wechat.php的檔案
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述編輯wechat.php,這截圖的是預設遮蔽的,看你個人需要釋放相關程式碼。並填上相關引數,app_id,mch_id等等。可在.env裡面配置,如果覺得麻煩可直接寫在default裡面。至此所有準備工作完畢。

程式碼塊

1,laravel路由

Route::middleware('wechat.oauth', 'wechat')->group(function () {
    Route::get('/pay', 'CourseController@pay');//支付路由
});
 Route::post('/order/notify', 'OrderController@notify');//回撥路由

注意
1.1,回撥路由必須在middleware中介軟體路由外面,否則微信請求不到。
1.2,回撥路由必須是post請求。
1.3,laravel框架必須取消回撥路由的csrf防護。在你專案的app/Http/Middleware/VerifyCsrfToken.php中加入如下程式碼:

protected $except = [
        'order/notify',//回撥路由取消csrf防護
    ];

2,支付流程
2.1,點選支付按鈕,ajax提交相應引數到後臺支付方法。
2.2,後臺接收資料,往你的訂單表裡插入一條訂單資料,狀態為0,也就是未支付狀態。
2.3,帶上這條訂單的訂單號,價格,請求微信換取prepay_id。
2.4,請求微信成功會返回支付所需要的引數,appid,timestamp等。返回前端js 調起支付。
2.5,支付後微信會將支付結果透過回撥返回,可根據返回資訊更改訂單狀態,或者進行其他操作。

3,專案程式碼
3.1,前端js程式碼

var a;
$('.pay').click(function () {
    var course_id=$(this).val();//購買商品的id
    var price=$('.price').text();//購買商品的價格
    $.ajax({
        type:"GET",
        url:"/wechat/course/pay",
        data:{course_id:course_id,price:price},
        success:function (config) {
                a = config;//請求微信成功返回的支付引數
                callpay()
        }
    })
});
//呼叫微信JS api 支付
function jsApiCall() {
    WeixinJSBridge.invoke(
        'getBrandWCPayRequest', a,
        function (res) {
            WeixinJSBridge.log(res.err_msg);
            if (res.err_msg == 'get_brand_wcpay_request:ok') {
                window.location.reload();
            } else {
                // alert('取消支付');
            }
        }
    );
}

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();
    }
}

3.2,控制器程式碼:

 //微信支付
    public function pay(Request $request)
    {
        $customer = session('wechat.customer');
        $customer_id = $customer['id'];
        $price = $request->get('price');
        $order = PcOrder::create([
                'user_id' => $customer_id,
                'out_trade_no' => date('Ymd') . str_pad(mt_rand(1, 99999), 5, '0', STR_PAD_LEFT) . rand(1000, 9999),
                'total_price' => $price,
                'status' => 0,//0未支付 1已支付
                'course_id' => $request->get('course_id'),
            ]);
            $original = session('wechat.oauth_user.default.original');
            $openid = $original['openid'];
            $payment = \EasyWeChat::payment(); // 微信支付例項

            $total_fee = $price * 100;//微信支付以分為單位 
            //統一下單
            $result = $payment->order->unify([
                'body' => '微信支付',
                'out_trade_no' => $order['out_trade_no'],
                'total_fee' => $total_fee,
                'notify_url' => 'https://www.********.com/order/notify', //回撥地址,用於接收微信支付結果
                'trade_type' => 'JSAPI',
                'openid' => $openid,
            ]);

            if ($result['result_code'] == 'SUCCESS' && $result['return_code'] == 'SUCCESS') {
                $prepayId = $result['prepay_id'];
                $jssdk = $payment->jssdk;
                $config = $jssdk->sdkConfig($prepayId);
                return $config;
            } else {
                return $result;
            }
    }

注意
1,如果支付時出現報錯,timestame引數問題。這是easywechat底層檔案出錯了。
解決辦法:在你專案的vendor/overtrue/wechat/src/Payment/Jssdk/Client.php中把第70行和第71行程式碼遮蔽了就行。

3.3,回撥程式碼:

 /**
     * 微信測評支付回撥方法,修改訂單狀態
     * @return mixed
     */
    public function notify()
    {
        $payment = \EasyWeChat::payment();
        $response = $payment->handlePaidNotify(function ($message, $fail) {
            if ($message['return_code'] === 'SUCCESS' && $message['result_code'] === 'SUCCESS') {
                \Log::debug($message);
                 PcOrder::where('out_trade_no', $message['out_trade_no'])->update(['status' => 1, 'pay_time' => time()]);//更改訂單狀態
                //支付後,微信會在此處返回支付狀態,就是$message,回撥裡面列印不出來,可透過寫入日誌裡面檢視,支付成功後更改訂單狀態。當然你也可以進行其他操作。
                return true;
            } else {
                \Log::debug('我不買了');
                return $fail('失敗');
            }
        });
        return $response;
    }

3.4,回撥日誌:

[2019-11-27 19:00:03] local.DEBUG: array (
  'appid' => '**************',
  'bank_type' => 'CFT',
  'cash_fee' => '1',
  'fee_type' => 'CNY',
  'is_subscribe' => 'Y',
  'mch_id' => '*************',
  'nonce_str' => '*******',
  'openid' => '*****************',
  'out_trade_no' => '20191127733582017',
  'result_code' => 'SUCCESS',
  'return_code' => 'SUCCESS',
  'sign' => '************',
  'time_end' => '20191127190001',
  'total_fee' => '1',
  'trade_type' => 'JSAPI',
  'transaction_id' => '**************',
)  

結束

1,本人是一個萌新php,很多都不懂,這是我上班時碰到的問題,所以記錄下來,希望對和我一樣的新手有所幫助,如有疑問評論即可。
2,大佬們看到此文章如有錯誤之處請多多指教,萬分感謝。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章