一.準備工作
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 應用
- 註冊
ServiceProvider
:
Overtrue\LaravelWechat\ServiceProvider::class,
- 創建配置文件:
php artisan vendor:publish --provider="Overtrue\LaravelWechat\ServiceProvider"
-
請修改應用根目錄下的
config/wechat.php
中對應的項即可; -
(可選)添加外觀到
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>