1.准备
安装 overtrue/laravel-wechat
composer require "overtrue/laravel-wechat:~5.0"
创建配置文件:
php artisan vendor:publish --provider="Overtrue\LaravelWeChat\ServiceProvider"
API证书在商户平台->账户中心->API安全->API证书里下载解压,放到cert_path和key_path的路径下
修改应用根目录下的 config/wechat.php 中对应的参数 (这部分直接 copy /paste 就行了)
'payment' => [
'default' => [
'sandbox' => env('WECHAT_PAYMENT_SANDBOX', false),
'app_id' => env('WECHAT_PAYMENT_APPID', ''),
'mch_id' => env('WECHAT_PAYMENT_MCH_ID', 'your-mch-id'),
'key' => env('WECHAT_PAYMENT_KEY', 'key-for-signature'),
'cert_path' => env('WECHAT_PAYMENT_CERT_PATH', 'path/to/cert/apiclient_cert.pem'), // XXX: 绝对路径!!!!
'key_path' => env('WECHAT_PAYMENT_KEY_PATH', 'path/to/cert/apiclient_key.pem'), // XXX: 绝对路径!!!!
'notify_url' => env('WECHAT_PAYMENT_NOTIFY_URL',''), // 默认支付结果通知地址
],
// ...
],
需要配置的就是上面这个数组里的内容,但其实都是需要在 .env 文件中配置的:
WECHAT_PAYMENT_SANDBOX=false
WECHAT_PAYMENT_APPID=xxxxxxxxxxxx //自己的公众号APPID
WECHAT_PAYMENT_MCH_ID=xxxxxxxxx //自己的商户号(商户平台查看)
WECHAT_PAYMENT_KEY=xxxxxxxxxx //在商户平台->账户中心->API安全->API密钥里设置
WECHAT_PAYMENT_NOTIFY_URL='http://xxx.com/wechatpay/notify' //这个地址只要是外网能够访问到项目的任何地址都可以, 不是需要在微信那里配置的那种
SWAGGER_VERSION=3.0
安装 Simple QrCode 生成二维码的包
composer require simplesoftwareio/simple-qrcode
在config/app.php 的 providers 数组里添加服务提供者.
SimpleSoftwareIO\QrCode\QrCodeServiceProvider::class
在app/config/app.php 的 aliases 数组里添加别名
'QrCode' => SimpleSoftwareIO\QrCode\Facades\QrCode::class
2.开始
Html 部分(支付页面我这里叫aaa.php)
<html>
<head>
<script type="text/javascript" src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
</head>
<button type="button" id="order" class="btn btn-secondary btn-block">
扫码支付
</button>
<!-- 二维码, 随便放在当前页面的那里都可以,我这里用jquery从后台请求过来的-->
<div class="modal fade" id="qrcode" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-sm" role="document">
<div class="modal-content bg-transparent" style="border:none">
<div class="modal-body align-items-center text-center">
<p class="modal-title" id="exampleModalLabel" style="color:white">微信扫码支付</p>
<br>
{{--生成的二维码会放在这里--}}
<div id="qrcode2"></div>
</div>
</div>
</div>
</div>
<script>
$('#order').click(function () {
$.get('place_order',function (data) {
if (data['code'] == 200)
{
// alert(12);
$(#qrcode2).html(data['html'])
}
})
})
</script>
</html>
创建路由
Route::get('wechatpay/place_order', 'PaymentController@place_order');//微信统一下单路由
Route::get('wechatpay/paid', 'PaymentController@paid');
Route::get('wechatpay/aaa', 'PaymentController@aaa');//视图路由
微信根据上面请求中传参的 notify_url 请求我的服务器,发送支付结果给我,那么必然是 post 请求:
Route::post('wechatpay/notify', 'PaymentController@notify');//回调路由
取消 csrf 验证
微信服务器发起的 post 请求无法通过 csrf token 验证,所以必须取消用于微信的路由的验证
在 app/Http/Middleware/VerifyCsrfToken 文件中:
protected $except = [
//
'wechatpay/notify'
];
控制器PaymentController 里的支付逻辑
<?php
namespace App\Http\Controllers;
use App\Http\Controllers;
use Illuminate\Http\Request;
use EasyWeChat\Factory;
use SimpleSoftwareIO\QrCode\Facades\QrCode;
class PaymentController extends Controller
{
//支付页面视图
public function aaa()
{
return view('aaa');
}
// 请求微信接口的公用配置, 所以单独提出来
private function payment()
{
$config = [
// 必要配置, 这些都是之前在 .env 里配置好的
'app_id' => config('wechat.payment.default.app_id'),
'mch_id' => config('wechat.payment.default.mch_id'),
'key' => config('wechat.payment.default.key'), // API 密钥
'notify_url' => config('wechat.payment.default.notify_url'), // 通知地址
];
// 这个就是 easywechat 封装的了, 一行代码搞定, 照着写就行了
$app = Factory::payment($config);
return $app;
}
// 向微信请求统一下单接口, 创建预支付订单
public function place_order()
{
// 因为没有先创建订单, 所以这里先生成一个随机的订单号, 存在 pay_log 里, 用来标识订单, 支付成功后再把这个订单号存到 order 表里
$order_sn = date('ymd').substr(time(),-5).substr(microtime(),2,5);//订单号
// 根据文章 id 查出文章价格
$post_price = 1;//金额
// // 支付信息都写到支付日志表pay_log里
// PayLog::create([
// 'appid' => config('wechat.payment.default.app_id'),
// 'mch_id' => config('wechat.payment.default.mch_id'),
// 'out_trade_no' => $order_sn,
// 'post_id' => 12 //用户id
// ]);
$app = $this->payment();
$total_fee = env('APP_DEBUG') ? 1 : $post_price;//价格
// 用 easywechat 封装的方法请求微信的统一下单接口
$result = $app->order->unify([
'trade_type' => 'NATIVE', // 原生支付即扫码支付,商户根据微信支付协议格式生成的二维码,用户通过微信“扫一扫”扫描二维码后即进入付款确认界面,输入密码即完成支付。
'body' => '投资平台-订单支付', // 这个就是会展示在用户手机上巨款界面的一句话, 随便写的
'out_trade_no' => $order_sn,//订单号
'total_fee' => $total_fee,//金额
'spbill_create_ip' => request()->ip(), // 可选,如不传该参数,SDK 将会自动获取相应 IP 地址
]);
if ($result['result_code'] == 'SUCCESS') {
// // 如果请求成功, 微信会返回一个 'code_url' 用于生成支付二维码
$code_url = $result['code_url'];
return [
'code' => 200,
// // 订单编号, 用于在当前页面向微信服务器发起订单状态查询请求
'order_sn' => $order_sn,
// // 生成二维码
'html' => QrCode::size(200)->generate($code_url),
];
}
return $result['return_msg'];
}
// 接收微信回调支付状态的通知
public function notify()
{
$app = $this->payment();
// 用 easywechat 封装的方法接收微信的信息, 根据 $message 的内容进行处理, 之后要告知微信服务器处理好了, 否则微信会一直请求这个 url, 发送信息
$response = $app->handlePaidNotify(function($message, $fail){
// 首先查看 order 表, 如果 order 表有记录, 表示已经支付过了(业务逻辑)
// return_code 表示通信状态,不代表支付状态
if ($message['return_code'] === 'SUCCESS') {
// 用户是否支付成功
if ($message['result_code'] === 'SUCCESS') {
//支付成功后的业务逻辑
}
} else {
return $fail('通信失败,请稍后再通知我');
}
return true; // 返回处理完成
});
// 这里是必须这样返回的, 会发送给微信服务器处理结果
return $response;
}
}
请求微信查看订单接口
public function paid(Request $request)
{
$out_trade_no = $request->get('out_trade_no');
$app = $this->payment();
// 用 easywechat 封装的方法请求微信
$result = $app->order->queryByOutTradeNumber($out_trade_no);
if ($result['trade_state'] === 'SUCCESS')
return [
'code' => 200,
'msg' => 'paid'
];
}else{
return [
'code' => 202,
'msg' => 'not paid'
];
}
}
转载自https://learnku.com/articles/25760
完结,撒花。