首先、申请微信商户平台,申请微信支付,公众号关联微信商户平台

公众号可以通过jsapi来实现公众号微信支付

一、业务页面

@extends('m.order')    
    @section('content')
        <style type="text/css">
            input, textarea {
                border: 0;
                -webkit-appearance: none;
            }
        </style>
        <section class="container">
            <div class="pay_main">
                <div class="ay_ma1"><span>付款金额</span><em><i>¥</i>{{$total_price}}</em></div><!--ay_ma1-->
                <div class="ay_ma2">订单编号:{{$order_no}}</div><!--ay_ma2-->
                <div class="ay_ma2">付款方式</div><!--ay_ma2-->
                <div class="ay_ma3"><span>微信支付</span><label></label></div>
                {{--<div class="ay_ma3"><span>微信支付</span><label><input name="" type="radio" value="" checked></label></div>--}}
                <div class="ay_ma4">
                    <ul>
                        <button type="button" onclick="wxPay()" id="pay_button">确认付款</button>
                    </ul>
                </div><!--ay_ma4-->
            </div><!--pay_main-->
            <input type="hidden" id="order_no" value="{{$order_no}}">
            <input type="hidden" id="code" value="">
        </section>
    @endsection
    @section('js')
        <script type="text/javascript" src="/static/new/m/js/jweixin-1.4.0.js"></script>
        <script type="text/javascript" src="/static/new/m/js/pay.js"></script>
    @endsection

二、前端pay.js逻辑

    $(function () {    
        var layer;
        layui.use(['layer'], function () {
            layer = layui.layer;
        });
        $('#pay_button').hide();
        wxConfig();
        wx.ready(function(){
            $('#pay_button').show();
        });
    });
    function wxConfig() {
        var order_no = $('#order_no').val();
        $.ajax({
            type:"GET",
            url:"/wechat/pay",
            data:{order_no:order_no},
            success:function (config) {
                // 微信配置
                wx.config({
                    debug: false,
                    appId: config.appId,
                    timestamp: config.timeStamp,
                    nonceStr: config.nonceStr,
                    signature: config.signature,
                    jsApiList: ['chooseWXPay']
                });
            }
        });
    }
    function wxPayAuth(orderPayNo) {
        window.location.href = '/mp/oauth?targetUrl=/pay/request?orderPayNo=' + orderPayNo;
    }
    var jsApiConfig;
    function wxPay() {
        var order_no = $('#order_no').val();
        $.ajax({
            type:"GET",
            url:"/wechat/pay",
            data:{order_no:order_no},
            success:function (config) {
                jsApiConfig = config;//请求微信成功返回的支付参数
                callpay();
            }
        })
    }
    //调用微信JS api 支付
    function jsApiCall()
    {
        WeixinJSBridge.invoke(
            'getBrandWCPayRequest',jsApiConfig,
            function(res){
                //WeixinJSBridge.log(res.err_msg);
                //alert(res.err_code+res.err_desc+res.err_msg);
                if(res.err_msg == "get_brand_wcpay_request:ok" ) {
                    layer.msg('支付成功', {time: 1000, end: function () {
                        location.href = '/inquiry/index';
                    }});
                }else{
                    layer.msg('支付失败,请重试');
                }
            });
    }
    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();
        }
    }

三、服务端处理页面

    <?php    
    namespace App\Http\Controllers\M;
    use App\Library\Common;
    use App\Library\Y;
    use App\Models\Member\MemberConnect;
    use App\Models\Prod\Order;
    use App\Models\Prod\SaleOrder;
    use App\Services\Wechat\MenuService;
    use App\Services\Wechat\MessageService;
    use App\Services\Wechat\UserService;
    use Illuminate\Http\Request;
    use App\Http\Controllers\Controller;
    use Illuminate\Support\Facades\Auth;
    use Illuminate\Support\Facades\Cache;
    use Illuminate\Support\Facades\Log;
    class WeChatController extends Controller
    {
        //
         /**
          * 处理微信的请求消息
          *
          * @return string
          */
        /* public function serve()
         {
              Log::info('request arrived.'); # 注意:Log 为 Laravel 组件,所以它记的日志去 Laravel 日志看,而不是 EasyWeChat 日志
              $app = app('wechat.official_account');
              $app->server->push(function($message){
                   return "欢迎关注 一览商城!";
              });
              return $app->server->serve();
         }*/
         public function serve(MessageService $messageService)
         {
              Log::info('request arrived.'); # 注意:Log 为 Laravel 组件,所以它记的日志去 Laravel 日志看,而不是 EasyWeChat 日志
              $app = app('wechat.official_account');
              $app->server->push(function($message) use($messageService){
                   return $messageService->index($message);
              });
              return $app->server->serve();
         }
         /**
          * 登录时请求验证
          * @return mixed
          */
         public function login_oauth(){
              Log::info('start', ['login_oauth']);
              $member_id= isset(auth('member')->user()->id) ?auth('member')->user()->id : 0;
              //判断是否存在 openid
              if(!Common::getOpenid($member_id)){
                   $app = app('wechat.official_account');
                   return $response = $app->oauth->scopes(['snsapi_userinfo'])->redirect(route('m.login_callback'));
              }
              return redirect(route('m.member.index'));
          }
         /**
          * 登录时请求回调
          * @return mixed
          */
         public function login_callback(){
              Log::info('start', ['login_callback']);
              $app = app('wechat.official_account');
              // 获取 OAuth 授权结果用户信息
              $user = $app->oauth->user();
              if(!$user){
                   Log::info('oauth_callback_user_error', ['none user']);
              }
              $openid = $user->getId();
              $UserService = new UserService();
              $user_info =$UserService->getUserInfo($openid);
              $member_id= isset(auth('member')->user()->id) ?auth('member')->user()->id : 0;
              //查询openid 有没有绑定 member
              $memberConnect = MemberConnect::where('openid', '=', $openid)->first();
              if(!$memberConnect){
                   //没保存先保存memberConnect
                   Common::createMemberConnect($user_info, 3);
              }
              //绑定openid memberid
              MemberConnect::where('openid', '=', $openid)->update(['member_id'=>$member_id]);
              //如果登录,则保存微信用户信息进cache
              if($member_id > 0){
                   Log::info('login_callback_cache', [$user_info]);
                   Cache::add("wx_user:".$member_id, $user_info);
              }
              return redirect(route('m.member.index'));
         }
         /**
          * 发起授权
          * @return mixed
          */
         public function oauth(){
              Log::info('start', ['oauth']);
              $member_id= isset(auth('member')->user()->id) ?auth('member')->user()->id : 0;
              //已登录状态
              if($member_id > 0){
                   $memberConnect = MemberConnect::where('member_id', '=', $member_id)->first();
                   //如果会员已绑定,直接跳转会员主页
                   if($memberConnect) return redirect(route('m.member.index'));
                   //如果会员没绑定,查看openid是否绑定
                   $openid = Common::getOpenid($member_id);
                   if($openid){
                        $memberConnect = MemberConnect::where('openid', '=', $openid)->first();
                        //存在则更新
                        if($memberConnect){
                             MemberConnect::where('openid', '=', $openid)->update(['member_id'=>$member_id]);
                             return redirect(route('m.member.index'));
                        }
                   }
              }
              $app = app('wechat.official_account');
              return $app->oauth->scopes(['snsapi_userinfo'])->redirect();
         }
         /**
          * 授权回调
          * @return mixed
          */
         public function callback(){
              Log::info('start', ['oauth_callback']);
              // 获取 OAuth 授权结果用户信息
              $app = app('wechat.official_account');
              $user = $app->oauth->user();
              if(!$user) Log::info('oauth_callback', ['none user']);
              $openid = $user->getId();
              $UserService = new UserService();
              $user_info =$UserService->getUserInfo($openid);
              //查询openid 有没有绑定 member
              $memberConnect = MemberConnect::where('openid', '=', $openid)->first();
              $member_id = 0;
              if(!$memberConnect){
                  //没保存先保存memberConnect
                  Common::createMemberConnect($user_info, 3);
              }else{
                   $member_id = $memberConnect->member_id;
              }
              if($member_id > 0){
                   //openid 已经跟会员member绑定,则默认登录
                   Auth::guard('member')->loginUsingId($member_id);
                   //加入openid缓存
                   Cache::add("wx_user:".$member_id, $user_info);
                   Log::info('wechat login email', [auth('member')->user()->email]);
                   return redirect(route('m.member.index'));
              }
              if($member_id ==0 ){
                 //openid还没跟会员member绑定,提醒用户去设置绑定
                 return redirect(route('m.bind_account', array('openid'=>$openid)));
              }
         }
         public function wxMenu(Request $request,MenuService $menuService){
              $buttons = [
                   [
                        "name" => "我要采购",
                        "sub_button" => [
                             [
                                  "type" => "view",
                                  "name" => "发布采购",
                                  "url"  => "http://m.bychem.com/inquiry/add"
                             ],
                             [
                                  "type" => "view",
                                  "name" => "采购管理",
                                  "url"  => "http://m.bychem.com/inquiry/lists?type=quote"
                             ],
                             [
                                  "type" => "view",
                                  "name" => "采购订单",
                                  "url"  => "http://m.bychem.com/order/lists?type=pay"
                             ],
                        ],
                   ],
                   [
                        "name" => "我要销售",
                        "sub_button" => [
                             [
                                  "type" => "view",
                                  "name" => "发布产品",
                                  "url"  => "http://m.bychem.com/sale/goods_add"
                             ],
                             [
                                  "type" => "view",
                                  "name" => "产品管理",
                                  "url"  => "http://m.bychem.com/sale/goods_list"
                             ],
                             [
                                  "type" => "view",
                                  "name" => "询盘管理",
                                  "url"  => "http://m.bychem.com/sale/lists"
                             ],
                             [
                                  "type" => "view",
                                  "name" => "销售订单",
                                  "url"  => "http://m.bychem.com/sale/order"
                             ],
                        ],
                   ],
                   [
                        "name" => "会员中心",
                        "sub_button" => [
                             [
                                  "type" => "view",
                                  "name" => "注册/登录",
                                  "url"  => "http://m.bychem.com/users/sign_in"
                             ],
                             [
                                  "type" => "view",
                                  "name" => "会员中心",
                                  "url"  => "http://m.bychem.com/member/index"
                             ],
                             [
                                 "type" => "click",
                                 "name" => "联系客服",
                                 "key" => "CONTACT_KEFU"
                            ],
                        ],
                   ],
              ];
              return $menuService->index($request,$buttons);
         }
         /**
          * 公众号微信支付成功回调
          * @param Request $request
          * @return mixed
          */
         public function wechat_notify(Request $request){
              Log::info('start', ['wechat mp notify']);
              $payment = app('wechat.payment');
              $response = $payment->handlePaidNotify(function ($message, $fail) {
                   Log::info('wechat mp notify msg', [$message]);
                   if ($message['return_code'] === 'SUCCESS' && $message['result_code'] === 'SUCCESS') {
                        Order::where('id','=', $message['out_trade_no'])->update(['is_pay' => 1,'status' => 2,'trade_no'=>$message['transaction_id'],'pay_method'=>'微信']);//更改订单状态
                        //更新销售合同支付状态
                        SaleOrder::where('order_id','=',$message['out_trade_no'])->update(['is_pay'=>1]);
                        //支付后,微信会在此处返回支付状态,就是$message,回调里面打印不出来,可通过写入日志里面查看,支付成功后更改订单状态。当然你也可以进行其他操作。
                        return true;
                   } else {
                        return $fail('失败');
                   }
              });
              return $response;
         }
         /**
          * 发起支付
          * 组合微信支付需要参数
          * @param Request $request
          * @return mixed
          */
         public function pay(Request $request){
              Log::info('start',['wechat paying']);
              $order_no = $request->get('order_no');
              $member_id =  isset(auth('member')->user()->id) ?auth('member')->user()->id : 0;
              //判断是否有权限操作此订单
              $order = Order::where('order_no', '=', $order_no)->first();
              if($order->user_id != $member_id) return Y::error('没有权限操作!');
              $total_price = $order->total_price;
              $total_price = $total_price * 100;//微信支付以分为单位
              $openid = Common::getOpenid($member_id);
              if(!$openid) return Y::error('没有openid!请重新登录');
              Log::info('wechat repay',[$order_no, $member_id,$total_price, $openid]);
              $payment = app('wechat.payment');
              //统一下单
              $result = $payment->order->unify([
                   'body' => '微信支付',
                   'out_trade_no' => $order->id,
                   'total_fee' => $total_price,
                   //'notify_url' => 'http://m.bychem.com/wechat/payments/wechat-notify', //回调地址,用于接收微信支付结果
                   'notify_url' => route('m.wechat_notify'), //回调地址,用于接收微信支付结果
                   'trade_type' => 'JSAPI',
                   'openid' => $openid,
              ]);
              Log::info('wechat payment result',[$result]);
              if ($result['result_code'] == 'SUCCESS' && $result['return_code'] == 'SUCCESS') {
                   $prepayId = $result['prepay_id'];
                   $jssdk = $payment->jssdk;
                   $config = $jssdk->sdkConfig($prepayId);
                   $config['timestamp'] = strval(time());
                   $config['timeStamp'] = strval(time());
                   Log::info('wechat config',[$config]);
                   return $config;
              } else {
                   Log::info('wechat config un_success',[$result]);
                   return $result;
              }
         }
    }

四、csrf排除

    <?php    
    namespace App\Http\Middleware;
    use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
    class VerifyCsrfToken extends Middleware
    {
        /**
         * Indicates whether the XSRF-TOKEN cookie should be set on the response.
         *
         * @var bool
         */
        protected $addHttpCookie = true;
        /**
         * The URIs that should be excluded from CSRF verification.
         *
         * @var array
         */
        protected $except = [
            'wechat_notify',
            'ali_notify',
            'wechat',
            'wechat/*',
            'payments/*'
        ];
    }