Laravel使用EasyWechat,3分钟完成微信支付

费子濯
2023-12-01

一.准备工作

1.下载微信官方PHP的SDK,里面有个rootca.pem要用到,在php.ini里配置curl.cainfo=你存放rootca.pem的绝对路径,重启PHP

2.composer集成easywechat的laravel版本,具体怎么使用点这里

2.1

composer require "overtrue/laravel-wechat:~3.0"

2.2

Laravel 应用

  1. 注册 ServiceProvider:
Overtrue\LaravelWechat\ServiceProvider::class,
  1. 创建配置文件:
php artisan vendor:publish --provider="Overtrue\LaravelWechat\ServiceProvider"
  1. 请修改应用根目录下的 config/wechat.php 中对应的项即可;

  2. (可选)添加外观到 config/app.php 中的 aliases 部分:

'EasyWeChat' => Overtrue\LaravelWechat\Facade::class,


二.创建控制器WechatController.php

或许有些人看到这里有一些懵,讲一下流程:

1.自己创建一个订单(就是数据库里新建一个订单记录,相信谁都会吧。。),这个订单里有金额,购买人的user_id,支付状态status等信息

 

2.创建好订单后,这时我们就要去微信端申请支付了,目的是申请微信的预支付ID,有了预支付ID才能付款。拿订单id是为了拿到里面的金额money信息,而且还要给这个订单添加一个out_trade_no的字段信息,这个out_trade_no的信息,就是将来微信回调的时候来找你这个订单的。

 

3.支付完成后,微信会一直POST你的回调地址(注意是post,所以要去中间件里,关掉这个回调地址的csrf验证),这个回调方法就是通过out_trade_no找到这个订单,然后更改订单状态的。

 

PS:我这里给出的都是function方法,具体路由还是去routes.php需要自己建哦。

 

 

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use App\Http\Requests;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Input;
use Auth,Redirect;
use Validator;

use App\Models\ExampleOrder; //这是我的模型

use EasyWeChat\Foundation\Application;
use EasyWeChat\Payment\Order;
use EasyWeChat;

class WechatController extends Controller
{
	protected function options(){ //选项设置
		return [
            // 前面的appid什么的也得保留哦
            'app_id' => 'xxxxxxxxx', //你的APPID
            'secret'  => 'xxxxxxxxx',     // AppSecret
            // 'token'   => 'your-token',          // Token
            // 'aes_key' => '',                    // EncodingAESKey,安全模式下请一定要填写!!!
            // ...
            // payment
            'payment' => [
                'merchant_id'        => '你的商户ID,MCH_ID',
                'key'                => '你的KEY',
                // 'cert_path'          => 'path/to/your/cert.pem', // XXX: 绝对路径!!!!
                // 'key_path'           => 'path/to/your/key',      // XXX: 绝对路径!!!!
                'notify_url'         => '你的回调地址',       // 你也可以在下单时单独设置来想覆盖它
                // 'device_info'     => '013467007045764',
                // 'sub_app_id'      => '',
                // 'sub_merchant_id' => '',
                // ...
            ],
        ];
	}
//传入订单ID即可,我这里是通过订单,来查询该订单的金额,当然你也可以自定义金额
    public function pay(){
 	$id = Input::get('order_id');//传入订单ID
 	$order_find = ExampleOrder::find($id); //找到该订单
 	$mch_id = xxxxxxx;//你的MCH_ID
        $options = $this->options();
        $app = new Application($options);
        $payment = $app->payment;
        $out_trade_no = $mch_id.date("YmdHis"); //拼一下订单号
        $attributes = [
            'trade_type'       => 'APP', // JSAPI,NATIVE,APP...
            'body'             => '购买CSDN产品',
            'detail'           => $order_find->info, //我这里是通过订单找到商品详情,你也可以自定义
            'out_trade_no'     => $out_trade_no,
            'total_fee'        => $order_find->money*100, //因为是以分为单位,所以订单里面的金额乘以100
            // 'notify_url'       => 'http://xxx.com/order-notify', // 支付结果通知网址,如果不设置则会使用配置里的默认地址
            // 'openid'           => '当前用户的 openid', // trade_type=JSAPI,此参数必传,用户在商户appid下的唯一标识,
            // ...
        ];
        $order = new Order($attributes);
        $result = $payment->prepare($order);
	if ($result->return_code == 'SUCCESS' && $result->result_code == 'SUCCESS'){
	    $order_find->out_trade_no = $out_trade_no; //在这里更新订单的支付ID
	    $order_find->save();
	    // return response()->json(['result'=>$result]);
            $prepayId = $result->prepay_id;
            $config = $payment->configForAppPayment($prepayId);        
            return response()->json($config);
	}

    }


//下面是回调函数
    public function paySuccess(){
    	$options = $this->options();
        $app = new Application($options);
    	$response = $app->payment->handleNotify(function($notify, $successful){
		    // 使用通知里的 "微信支付订单号" 或者 "商户订单号" 去自己的数据库找到订单
		    $order = ExampleOrder::where('out_trade_no',$notify->out_trade_no)->first();
		    if (count($order) == 0) { // 如果订单不存在
		        return 'Order not exist.'; // 告诉微信,我已经处理完了,订单没找到,别再通知我了
		    }
		    // 如果订单存在
		    // 检查订单是否已经更新过支付状态
		    if ($order->pay_time) { // 假设订单字段“支付时间”不为空代表已经支付
		        return true; // 已经支付成功了就不再更新了
		    }
		    // 用户是否支付成功
		    if ($successful) {
		        // 不是已经支付状态则修改为已经支付状态
		        $order->pay_time = time(); // 更新支付时间为当前时间
		        $order->status = 6; //支付成功,
		    } else { // 用户支付失败
		        $order->status = 2; //待付款
		    }
		    $order->save(); // 保存订单
		    return true; // 返回处理完成
		});
    }


    
}

 

 

 

 

 

 

大功告成,是不是很EASY呀~

 

 

改成微信网页端支付也很简单,多传一个参数open_id,然后把类型改为JSAPI,然后去渲染一个页面就行

 

    public function pay(){
 	$id = Input::get('order_id');//传入订单ID
 	$order_find = ExampleOrder::find($id); //找到该订单
 	$mch_id = xxxxxxx;//你的MCH_ID
        $options = $this->options();
        $app = new Application($options);
        $payment = $app->payment;
        $out_trade_no = $mch_id.date("YmdHis"); //拼一下订单号
        $attributes = [
            'trade_type'       => 'JSAPI', // JSAPI,NATIVE,APP...
            'body'             => '购买CSDN产品',
            'detail'           => $order_find->info, //我这里是通过订单找到商品详情,你也可以自定义
            'out_trade_no'     => $out_trade_no,
            'total_fee'        => $order_find->money*100, //因为是以分为单位,所以订单里面的金额乘以100
            // 'notify_url'       => 'http://xxx.com/order-notify', // 支付结果通知网址,如果不设置则会使用配置里的默认地址
            'openid'           => '当前用户的 openid', // trade_type=JSAPI,此参数必传,用户在商户appid下的唯一标识,
            // ...
        ];
        $order = new Order($attributes);
        $result = $payment->prepare($order);
	if ($result->return_code == 'SUCCESS' && $result->result_code == 'SUCCESS'){
	    $order_find->out_trade_no = $out_trade_no; //在这里更新订单的支付ID
	    $order_find->save();
	    // return response()->json(['result'=>$result]);
            $prepayId = $result->prepay_id;
            $config = $payment->configForAppPayment($prepayId);        
            return response()->json($config);
	}

    }


渲染页面的方法

 

 

 

 

public function payOrder(){ //支付订单页面
        $order_id = Input::get('order_id');
        $order = ExampleOrder::find($order_id);
        $config = $this->payment($order->pay_id);
        $js = EasyWeChat::js();
        return view('home.mobile.pay_order')
            ->withConfig($config)
            ->withJs($js)
            ->withOrder($order);
    }


然后前端实现

 

 

<div>
    <h1>支付{{$order->money}}元</h1>
    <br>
    <input type="button" value="支付" id="pay">
</div>

<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js" type="text/javascript" charset="utf-8"></script>

<script type="text/javascript" charset="utf-8">
        wx.config(<?php echo $js->config(array('chooseWXPay'), false) ?>); //这里改成true就可以打开微信js的调试模式

        // wx.ready(function(){
        //     wx.chooseWXPay({
        //         timestamp: {{$config["timestamp"]}},
        //         nonceStr: '{{$config["nonceStr"]}}',
        //         package: '{{$config["package"]}}',
        //         signType: '{{$config["signType"]}}',
        //         paySign: '{{$config["paySign"]}}', // 支付签名
        //         success: function (res) {
        //             // 支付成功后的回调函数
        //             window.location.href='/myorder';
        //         }
        //     });
        // });
        $('#pay').click(function(){
            wx.chooseWXPay({
                timestamp: {{$config['timestamp']}},
                nonceStr: '{{$config['nonceStr']}}',
                package: '{{$config['package']}}',
                signType: '{{$config['signType']}}',
                paySign: '{{$config['paySign']}}', // 支付签名
                success: function (res) {
                    // 支付成功后的回调函数
                    window.location.href='/mobile';
                }
            });
        });
        
        
</script>

 

 

 

 

 

 

 

 类似资料: