1. 程式人生 > >Laravel使用EasyWechat,3分鐘完成微信支付

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

一.準備工作

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>