Laravel+easywechat 实现公众号微信支付
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 协议》,转载必须注明作者和本文链接
写得很好。很实用
改vendor代码一般情况下是不可取的,我记得不用改的话也可以的,可能是你哪里出错了。建议再研究一下,如果真的是bug的话,可以上Github上提issue,而不是自己改vendor。否则每次composer install 之后你还需要手动改文件。
支付回调建议判断下金额是否相符会更好
laravel6.0用easywechat会有不兼容的情况吗?
不错
运行
composer require overtrue/wechat:~4.0命令和
php artisan vendor:publish --provider="Overtrue\LaravelWeChat\ServiceProvider"命令后 ,
没有生成wechat.php文件请问怎么回事
和楼主一样的逻辑。
前端无法拉起支付密码输入窗口,请问通常什么原因?