PHP使用Laravel-Pay组件快速接入微信JSAPI支付(微信公众号支付) 
本文为系列文章,接下来分别会讲解如何接入微信 与 支付宝 支付并完成支付的保姆式教程,各支付代码示例细节详见页尾链接。  
  
 
  
前言 
本篇介绍微信 H5、JSAPI(公众号)、APP、小程序支付、Native支付(手机扫网站二维码进行支付)、需要的基础资料  
  
一、前期准备与花费明细(仅供参考) 
| 项目名 | 花费 | 功能 | 
|---|
 | 公众号认证 | 300 | JSAPI支付 |  | 微信开放平台认证 | 300 | APP支付、网站扫码支付(Native支付) |  | 微信小程序认证 | 300 | 小程序支付 |  | 微信商户平台认证 | 300 | H5基础支付 |   
注意:  这里必须要开通的是微信商户平台。剩下的更你的实际业务需求进行开通。  
使用composer下载laravel-pay组件  
composer require yansongda/pay -vvv
  
laravel-pay官网地址:https://pay.yansongda.cn/docs/v2/installation.html  laravel-pay Git项目地址:https://github.com/yansongda/pay/tree/v2  
二、支付类型 
1.微信公众号支付(JSAPI支付) 
支付原理: 
1.前端获取微信code
2.前端发送code到我方后台换openid
3.带着openid请求我方后台拉起支付
4.前端更具后台返回值判断是否拉起 微信付款页面
5.用户在手机上进行付款操作
6.用户付款结束后,微信服务器向我方服务器发送请求,告诉我们用户已经支付完了
7.我方后台通过支付完成异步回调修改数据库中的订单支付状态值。
8.End
  
代码如下(示例):  
前端html支付示例 
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<button onclick="wechatPay()">点我拉起微信支付</button>
</body>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script>
<script>
    var code = getQueryVariable('code');
    var openid;
    
    
    if(code){
        
        $.ajax({
            type : "POST", 
            url : "http://请求后端获取openid路由地址",
            data : {
                '_token':"{{ csrf_token() }}",
                'code':code
            },
            success : function(result) {
                openid = result.data.openid;
                
            }
        });
    }else{
        
        var appid = "公众号appid";
        var redirect_uri = "填获取code后重定向的地址";
        var state = '';
        var url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid="+ appid +"&redirect_uri="+ redirect_uri +"&response_type=code&scope=snsapi_base&state="+ state +"#wechat_redirect";
        window.location.href = url;
    }
    
    function getQueryVariable(variable)
    {
        var query = window.location.search.substring(1);
        var vars = query.split("&");
        for (var i=0;i<vars.length;i++) {
            var pair = vars[i].split("=");
            if(pair[0] == variable){return pair[1];}
        }
        return(false);
    }
    
    function wechatPay() {
        if(!open_id){
            alert('500:获取openid失败');
            return false;
        }
        $.ajax({
            type : "POST", 
            url : "请求我方后台接口,向微信服务器发起支付请求wechatPay.php",
            data : {
                '_token':"{{ csrf_token() }}",
                "open_id" : open_id,
            },
            success : function(res) {
                
                if (res.success) {
                    
                    if (typeof WeixinJSBridge == "undefined"){
                        if( document.addEventListener ){
                            document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
                        }else if (document.attachEvent){
                            document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
                            document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
                        }
                    }else{
                        onBridgeReady(res.data);
                    }
                }
                
                if(res.show_msg){
                    alert(res.msg)
                }
            }
        });
    }
    
    function onBridgeReady(data){
        WeixinJSBridge.invoke(
            'getBrandWCPayRequest', {
                "appId":data.appId,     
                "timeStamp":data.timeStamp,         
                "nonceStr":data.nonceStr, 
                "package":data.package,
                "signType":data.signType,         
                "paySign":data.paySign 
            },
            function(res){
                if(res.err_msg == "get_brand_wcpay_request:ok" ){
                    
                    
                    
                    window.location = "访问我方自主查询支付结果页面";
                }
            });
    }
</script>
</html>
  
后端PHP拉起支付以及用户支付成功后异步回调示例 
<?php
namespace App\Http\Controllers\H5;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Yansongda\Pay\Log;
use Yansongda\Pay\Pay;
class WechatPayController extends Controller
{
    private $wechatPay = [
        'appid' => '', 
        'app_id' => '这里填公众号 APPID', 
        'app_secret' => '这里填公众号开发者密码AppSecret', 
        'miniapp_id' => '', 
        'mch_id' => '微信商户平台的商户号',
        'key' => '商户平台的商户号秘钥',
        'notify_url' => 'https://www.xxx.com/wechatPay/wechatPayNotify',
        'cert_client' => './cert/apiclient_cert.pem', 
        'cert_key' => './cert/apiclient_key.pem',
        'log' => [ 
            'file' => './login/wechat.log',
            'level' => 'debug', 
            'type' => 'single', 
            'max_file' => 30, 
        ],
        'http' => [ 
            'timeout' => 5.0,
            'connect_timeout' => 5.0,
            
        ],
        
    ];
    
    protected function send($code = 200,$success = false,$show_msg = false,$msg = '',$data=[]){
        return [
            'code' => $code,
            'success' => $success,
            'show_msg' => $show_msg,
            'msg' => $msg,
            'data' => $data
        ];
    }
    
    public function wechatMpPay(Request $request)
    {
        $open_id = $request->open_id;
        $order_pay = [
            'openid' => $open_id,
            'out_trade_no' => time(),
            'total_fee' => 1, 
            'body' => '支付测试Demo',
        ];
        $pay = Pay::wechat($this->wechatPay)->mp($order_pay);
        if($pay){
            return $this->send(200,true,false,'成功',$pay);
        }
        return $this->send(500,false,false,'支付接口异常');
    }
    
    public function wechatPayNotify()
    {
        $pay = Pay::wechat($this->wechatPay);
        try {
            $data = $pay->verify(); 
            Log::debug('Wechat notify', $data->all());
            file_put_contents('wechat_log.txt',$data->all());
            
            if ($data->return_code == "SUCCESS" && $data->result_code == "SUCCESS") {
                
                file_put_contents('wechat_log.txt','支付成功啦!');
                
                
                $str = '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
                return $str;
            }
        } catch (\Exception $exception) {
            Log::debug('Wechat BUG', $exception->getMessage());
            file_put_contents('wechat_log.txt','支付回调异常:'.$exception->getMessage());
        }
        $str = '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
        return $str;
        
    }
    
    public function isPaySuccess($order_id)
    {
        
        
        $isPaySuccess = Order::where([
            ['id',$order_id],
            ['is_pay',1]
        ])->first();
        
        if($isPaySuccess){
            
            return redirect()->route('h5.goods.goodsList',$isPaySuccess['students_id'])->with('success','支付成功');
            
        }else{
            
            return redirect()->route('h5.goods.goodsList',$isPaySuccess['students_id'])->with('error','error');
        }
    }
    
    public function getWechatMpOpenid(Request $request){
        $code = (string)$request->code;
        $appid = $this->wechatPay['app_id'];
        $secret = $this->wechatPay['app_secret'];
        $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={$appid}&secret={$secret}&code={$code}&grant_type=authorization_code";
        
        $ch = curl_init();
        
        curl_setopt($ch, CURLOPT_URL,$url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        
        $response = curl_exec($ch);
        
        curl_close($ch);
        $response = json_decode($response,true);
        return [
            'code'=>200,
            'data'=>[
                'openid'=>$response['openid'],
                'array'=>$response
            ]
        ];
    }
}
  
该处使用的url网络请求的数据。  
  
微信官方后台 
1.微信公众平台配置我方项目域名,如下图,若与下图不符,请检查你的公众号是否没有进行认证处理  
   
要是你不想花钱测试支付,可以在侧边栏 开发→开发者工具→公众平台测试账号 中申请测试账号,并进行支付测试,需要注意:你在微信官方给测试账号中支付的花销是退不回来的!!!退不回来的!!!退不回来的!!!  2.微信公众号在侧边栏 微信支付 与商户号进行绑定操作。  3.登录微信商户平台,开通JSAPI支付产品  4.在微信商户平台进行商户号与微信公众号的绑定操作与相关配置。 
                
                
                
        
    
 
 |