laravel5.5通过Easywechat组件实现PC网站微信支付(Native支付)

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

完结,撒花。

展开阅读全文

没有更多推荐了,返回首页