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,大佬們看到此文章如有錯誤之處請多多指教,萬分感謝。