回調(diào)函數(shù)
$response = $app->handlePaidNotify(function ($message, $fail) {
// 你的邏輯
return true;
// 或者錯(cuò)誤消息
$fail('Order not exists.');
});
$response->send(); // Laravel 里請(qǐng)使用:return $response;
注意
(1).wechat發(fā)送回調(diào)是通過post方式,在路由處定義了之后祥国,還需要在laravel項(xiàng)目中排除token驗(yàn)證,我建議在中間件中VerifyCsrfToken.php進(jìn)行排除路由。
protected $except = [
'/pay_success_notify',
];
- 重點(diǎn)荒典!重點(diǎn)!重點(diǎn)吞鸭! 回調(diào)這里的處理可以說是重中之重寺董,這里出岔子,可能會(huì)造成 用戶支付成功后刻剥,微信的 * 回調(diào)沒有進(jìn)來 * 遮咖,后臺(tái)回調(diào)的邏輯就沒有執(zhí)行,導(dǎo)致用戶錢花了造虏,東西沒買上(即你的服務(wù)器上沒有執(zhí)行給付費(fèi)用戶修改支付狀態(tài)等數(shù)據(jù)庫操作)御吞。
另一種后果,如果沒有正確返回微信參數(shù)漓藕,微信會(huì)多次發(fā)送回調(diào)信息來提醒你支付成功了魄藕,導(dǎo)致你的服務(wù)器 * 接受回調(diào)函數(shù)多遍 * 。而此時(shí)你也馬馬虎虎撵术,沒有在支付成功的邏輯上對(duì)用戶的支付狀態(tài)進(jìn)行判斷背率,導(dǎo)致邏輯用戶充一次錢,在數(shù)據(jù)庫卻重復(fù)執(zhí)行了好幾次相關(guān)數(shù)據(jù)庫操作嫩与。前者坑了付費(fèi)用戶寝姿,后者坑了你的公司,這里如果不注意的話划滋,后果只會(huì)很嚴(yán)重饵筑,涉及到錢的地方要倍加小心。- 在回調(diào)路由指向的方法內(nèi)处坪,如果你的支付成功的邏輯成功運(yùn)行了根资,需要return true;如果沒有成功進(jìn)行數(shù)據(jù)庫操作同窘,需要返回false玄帕;或不返回,微信會(huì)再一次發(fā)送回調(diào)信息(post方式)想邦。
一些easywechat官方的建議:
這里需要注意的有幾個(gè)點(diǎn):
退款結(jié)果通知和掃碼支付通知的使用方法均類似裤纹。
handlePaidNotify
只接收一個(gè)Closure
匿名函數(shù)。該匿名函數(shù)接收兩個(gè)參數(shù)丧没,這兩個(gè)參數(shù)分別為:
$message
為微信推送過來的通知信息鹰椒,為一個(gè)數(shù)組锡移; -$fail
為一個(gè)函數(shù),觸發(fā)該函數(shù)可向微信服務(wù)器返回對(duì)應(yīng)的錯(cuò)誤信息漆际,微信會(huì)稍后重試再通知淆珊。該函數(shù)返回值就是告訴微信 “我是否處理完成”。如果你觸發(fā)
$fail
函數(shù)奸汇,那么微信會(huì)在稍后再次繼續(xù)通知你套蒂,直到你明確的告訴它:“我已經(jīng)處理完成了”,只有在函數(shù)里return true;
才代表處理完成茫蛹。handlePaidNotify
返回值$response
是一個(gè) Response 對(duì)象操刀,如果你要直接輸出,使用$response->send()
, 在一些框架里(如 Laravel)不是輸出而是返回:return $response
婴洼。
通常我們的處理邏輯大概是下面這樣(以下只是偽代碼):
$response = $app->handlePaidNotify(function($message, $fail){
// 使用通知里的 "微信支付訂單號(hào)" 或者 "商戶訂單號(hào)" 去自己的數(shù)據(jù)庫找到訂單
$order = 查詢訂單($message['out_trade_no']);
if (!$order || $order->paid_at) { // 如果訂單不存在 或者 訂單已經(jīng)支付過了
return true; // 告訴微信骨坑,我已經(jīng)處理完了,訂單沒找到柬采,別再通知我了
}
///////////// <- 建議在這里調(diào)用微信的【訂單查詢】接口查一下該筆訂單的情況欢唾,確認(rèn)是已經(jīng)支付 /////////////
if ($message['return_code'] === 'SUCCESS') { // return_code 表示通信狀態(tài),不代表支付狀態(tài)
// 用戶是否支付成功
if (array_get($message, 'result_code') === 'SUCCESS') {
$order->paid_at = time(); // 更新支付時(shí)間為當(dāng)前時(shí)間
$order->status = 'paid';
// 用戶支付失敗
} elseif (array_get($message, 'result_code') === 'FAIL') {
$order->status = 'paid_fail';
}
} else {
return $fail('通信失敗粉捻,請(qǐng)稍后再通知我');
}
$order->save(); // 保存訂單
return true; // 返回處理完成
});
$response->send(); // return $response;