什么是php動態(tài)網(wǎng)站開發(fā)知名的網(wǎng)絡(luò)推廣
注冊服務(wù)號,需進行微信認證,此時需繳費 300 元/年,必須是認證成功的服務(wù)號才能開通微信支付。
注冊微信支付商戶號
1、登錄 https://pay.weixin.qq.com/index.php/core/home/login?return_url=https%3A%2F%2Fpay.weixin.qq.com%2Findex.php%2Fextend%2Fpay_setting%2Fma
,
點擊 接入微信
,點擊 注冊微信支付商戶號
,按步驟 創(chuàng)建申請單
–填寫商戶資料
–確認提交
即可。 <按提示進行操作即可,步驟無比繁瑣>
2、管理員微信號關(guān)注 微信支付商家助手
,以上操作步驟完成并通過后,商家助手會收到 入駐申請進展通知---待簽約
,用管理員手機點進去,掃臉確認簽約即可,完成后商家助手會收到 入駐成功
信息。
3、接下來完成 APPID授權(quán)管理
,登錄到微信服務(wù)號首頁,找到 設(shè)置與開發(fā)---接口權(quán)限
,在右邊找到 微信支付接口---未獲得
,點擊 申請
。在 待關(guān)聯(lián)商戶號
一欄中,點擊 確認
,同意授權(quán)即可。
此時在 已關(guān)聯(lián)商戶號
一欄中顯示對應(yīng)內(nèi)容,返回 接口權(quán)限
頁面,查看右邊的 微信支付接口
顯示 已獲得
。
微信支付商戶后臺配置
1、微信商戶平臺(pay.weixin.qq.com)–>賬戶中心–>賬戶設(shè)置–>API安全–>設(shè)置API密鑰,密鑰需下載下來放到項目的根目錄。接下來設(shè)置 APIv2
秘鑰、設(shè)置 APIv3
秘鑰。
2、產(chǎn)品中心–>開發(fā)配置–>支付配置,在此添加 JSAPI支付授權(quán)目錄
,如下圖所示:
3、關(guān)聯(lián)服務(wù)號,如下圖:
4、登錄微信公眾服務(wù)號后臺,對公眾號進行功能設(shè)置,如下圖:
微信支付功能開發(fā)
1、打開 easyWeChat
官網(wǎng),找到 Laravel 5 拓展包,按步驟安裝 laravel-wechat
。
// 安裝easyWeChat包
composer require "overtrue/laravel-wechat:~5.1"// 創(chuàng)建配置文件
php artisan vendor:publish --provider="Overtrue\LaravelWeChat\ServiceProvider"
在
composer.json
中顯示的laravel-wechat
版本號為"overtrue/laravel-wechat": "^5.1",
。
在項目的
config
文件夾中自動生成wechat.php
文件。
2、在 config/wechat.php
中打開微信支付的配置,然后在 .env
文件中做如下配置:
WECHAT_DEBUG=true# 此配置是實現(xiàn)微信公眾號登錄認證的配置
WECHAT_OFFICIAL_ACCOUNT_APPID='微信公眾號的APPID'
WECHAT_OFFICIAL_ACCOUNT_SECRET='微信公眾號的開發(fā)者密碼(AppSecret)'
WECHAT_OFFICIAL_ACCOUNT_TOKEN='隨意字符串'WECHAT_PAYMENT_APPID='微信公眾號APPID'
WECHAT_PAYMENT_MCH_ID='微信支付商戶號'
WECHAT_PAYMENT_KEY='Hubei***********8'
3、添加下單和支付路由:
Route::prefix('order')->group(function () {// 下單Route::post('/', 'OrderController@store');// 支付Route::get('/pay/{id}', 'OrderController@pay');
});
4、創(chuàng)建訂單的控制器方法和模型以及數(shù)據(jù)表 orders
php artisan make:controller OrderControllerphp artisan make:model Models/Order// 模型里面添加黑名單
protected $guarded = [];// orders 表的字段,以下只是范例,可根據(jù)需求自行添加
id、customer_id、out_trade_no、status、total_price、created_at、pay_time、updated_at
我的表結(jié)構(gòu)如下:
5、在 Order
控制器里面的 store
方法,代碼如下:
use App\Models\Shop\Address;
use App\Models\Shop\Cart;
use App\Models\Shop\Order;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;// 下單
function store(Request $request)
{$carts = Cart::with('product')->where('customer_id', session('wechat.customer.id'))->get();// 防止用戶使用微信的后退按鈕,重新提交訂單,導(dǎo)致出現(xiàn)沒有數(shù)據(jù)的訂單if ($carts->isEmpty()) {return ['status' => 0, 'info' => ''];}$count = Cart::count_cart();$total_price = $count['total_price'];DB::beginTransaction();try {//生成訂單$order = Order::create(['out_trade_no'=> Order::make_orderNo(),'customer_id' => session('wechat.customer.id'),'total_price' => $total_price,'status' => 1]);//訂單地址$address = Address::find($request->address_id);$order->address()->create(['province' => $address['province'],'city' => $address['city'],'area' => $address['area'],'detail' => $address['detail'],'name' => $address['name'],'tel' => $address['tel'],]);$carts = Cart::with('product')->where('customer_id', session('wechat.customer.id'))->get();foreach ($carts as $cart) {//判斷庫存是否足夠if ($cart->product->stock != '-1' and $cart->product->stock - $cart->num < 0) {throw new \Exception('商品' . $cart->product->name . ", 目前僅剩下" . $cart->product->stock . " 件. \n請返回購物車, 修改訂單后再下單!");}//削減庫存數(shù)量if ($cart->product->stock != '-1') {$cart->product->decrement('stock', $cart->num);}//插入訂單商品表$order->order_products()->create(['product_id' => $cart->product_id,'num' => $cart->num]);}//清空購物車Cart::where('customer_id', session('wechat.customer.id'))->delete();} catch (\Exception $e) {//echo $e->getMessage();DB::rollback();return ['status' => 0, 'info' => $e->getMessage()];}DB::commit();return ['status' => 1, 'order_id' => $order->id];
}
6、在 Order
控制器里面的 pay
方法,代碼如下:
use App\Models\Shop\Order;
use EasyWeChat;// 微信支付
function pay($id)
{$payment = EasyWeChat::payment();// 第 1 步:查詢訂單并計算金額$order = Order::with('address')->find($id);// 第 2 步:統(tǒng)一下單$result = $payment->order->unify(['body' => '測試支付','out_trade_no' => $order->out_trade_no,'total_fee' => $order->total_price * 100,'notify_url' => 'https://shop.***.com/order/notify', // 支付結(jié)果通知網(wǎng)址'trade_type' => 'JSAPI','openid' => session('wechat.customer.openid'),]);// return $result; // 打印$result看是否有結(jié)果// 第 3 步:JSSDKif ($result['result_code'] == 'SUCCESS' && $result['return_code'] == 'SUCCESS') {$prepayId = $result['prepay_id'];$jssdk = $payment->jssdk;$json = $jssdk->sdkConfig($prepayId);// return $json; // 打印$json看是否有結(jié)果return view('wechat.order.show_pay', compact('order', 'json'));} else {return $result;}
}
接下來,我們來測試一下上述代碼,打印 return $result;
。打開 微信開發(fā)者工具
,進入商城首頁,依次添加商品到購物車、選擇地址、下單,會得到如下圖結(jié)果:
繼續(xù)測試,打印 return $json;
。就在上圖結(jié)果中刷新地址,你會得到如下結(jié)果:
7、在前端頁面底部增加 js
調(diào)用代碼如下:
<script>$(function () {$("#pay").click(function () {if (typeof WeixinJSBridge === 'undefined') {alert('請在微信在打開頁面!');return false;}WeixinJSBridge.invoke('getBrandWCPayRequest', {!! json_encode($json) !!}, function (res) {switch (res.err_msg) {case 'get_brand_wcpay_request:cancel':alert('您取消了支付!');break;case 'get_brand_wcpay_request:fail':alert('支付失敗!(' + res.err_desc + ')');break;case 'get_brand_wcpay_request:ok':alert('支付成功!');location.href = '/order';break;default:alert(JSON.stringify(res));break;}});})})
</script>
接下來測試是否能喚起微信支付密碼窗口,輸入密碼后顯示支付成功。
注:如有出現(xiàn)錯誤
調(diào)用支付 JSAPI 缺少參數(shù) timeStamp
,解決辦法:在你項目的vendor/overtrue/wechat/src/Payment/Jssdk/Client.php
中屏蔽兩行代碼就行。
public function sdkConfig(string $prepayId): array
{$config = $this->bridgeConfig($prepayId, false);// 屏蔽這兩行代碼// $config['timestamp'] = $config['timeStamp'];// unset($config['timeStamp']);return $config;
}
如有其他錯誤,可以在評論區(qū)交流。
微信支付回調(diào)
1、首先增加支付回調(diào)路由,注意此路由應(yīng)放在 middleware
中間件路由外面,回調(diào)路由請求必須是 post
//支付成功回調(diào)
Route::namespace('Wechat')->group(function () {Route::post('/order/notify', 'OrderController@notify');
});
2、laravel
框架必須取消回調(diào)路由的 csrf
防護。在你項目的 app/Http/Middleware/VerifyCsrfToken.php
中加入如下代碼:
protected $except = ['order/notify', // 回調(diào)路由取消csrf防護
];
3、回調(diào)代碼如下:
/*** 微信支付回調(diào)方法,修改訂單狀態(tài)* @return mixed*/
function notify()
{$payment = EasyWeChat::payment();$response = $payment->handlePaidNotify(function ($message, $fail) {if ($message['return_code'] === 'SUCCESS' && $message['result_code'] === 'SUCCESS') {// \Log::debug($message);Order::where('out_trade_no', $message['out_trade_no'])->update(['status' => 2, 'pay_time' => Carbon\Carbon::now()]);//更改訂單狀態(tài)//支付后,微信會在此處返回支付狀態(tài),就是$message,回調(diào)里面打印不出來,可通過寫入日志里面查看,支付成功后更改訂單狀態(tài)。當然你也可以進行其他操作。return true;} else {// \Log::debug('我不買了');return $fail('失敗');}});return $response;
}
4、最后測試如下:
支付流程總結(jié)
1、點擊支付按鈕,js
提交相應(yīng)參數(shù)到后臺支付方法。
2、后臺接收請求,往你的訂單表里插入一條訂單數(shù)據(jù),狀態(tài)為 1
,也就是未支付狀態(tài)。
3、帶上這條訂單的訂單號、價格,請求微信換取 prepay_id
。
4、請求微信成功會返回支付所需要的參數(shù),appid
,timestamp
等。返回前端 js
調(diào)起支付。
5、支付后微信會將支付結(jié)果通過回調(diào)返回,可根據(jù)返回信息修改訂單狀態(tài)。
參考文獻:https://learnku.com/articles/37459