[TOC]
這一節相對來說有點兒長,請耐心閱讀!
## 回調是個什么東西
也許有的童鞋會問:為什么要回調操作啊?
回調是個什么東西?現實場景是這樣的,我在支付寶付了錢了,它會返回給我一些信息,是支付成功還是支付失敗!
如果支付成功呢?它會把支付成功的相關信息返回給我,我可以將之標記為**“已支付”**,將“返回的信息”保存到當前支付的數據表當中!
如果支付失敗呢?它會把支付失敗的相關信息返回給我,我可以將之標記為**“支付失敗”**,請重新支付!
## 同步接收 和 異步接收
>在支付寶中,回調包括兩個步驟 `同步接收通知` 和 `異步接收通知` 。它們有什么區別呢?
我們在實際場景中,分為兩步,我購買完一件商品后,可能有兩個操作。
第1個操作呢?我繼續等支付寶的頁面,進行跳轉到本地的“支付成功”提示
第2個操作呢?我馬上關閉頁面。走人了……
那么在第1個操作中,我們就叫“同步接收通知”,支付寶官方叫`return_url`,跳轉后立即告訴服務器接收到通知!(你可以修改數據庫,并且顯示“支付成功”或者“支付失敗”的界面!)
同理在第2個操作中,我們就叫“異步接收通知”,支付寶官方叫`notify_url`。也就是說:就算你走了,我也給告訴你的服務器。(你可以寫修改你的數據庫的邏輯代碼)!并縣城支付寶會按照一定的頻率往我們的服務器發送異步post的支付結果通知。
## 怎樣調試收到的支付狀態通知(重要)
因為接收到通知,我們一般無法用調試工具調試,比如`xdebuig`,那么我們怎么跟蹤這些問題呢?
我們只需要增加一行代碼就可以了,如下:
```
file_put_contents('./notify.txt', json_encode($_POST));
```
這個 `notify.txt` 文件會放到根目錄下,如果在`Linux`服務器下的話,請手動`touch`,并`chmod`給予權限!有的同學不知道,那么我把代碼寫上!以下代碼在根目錄下操作:
```
touch return.txt
touch notify.txt
chmod -R 777 return.txt
chmod -R 777 notify.txt
chmod -Rf 777 Application/Runtime
```
回調完整代碼如下所示:
```
<?php
namespace Api\Controller;
use Think\Controller;
/**
* 支付寶
*/
class AlipayController extends Controller {
/**
* return_url接收頁面
*/
public function alipay_return(){
// 下面的file_put_contents是用來簡單查看異步發過來的數據 測試完可以刪除;
file_put_contents('./return.txt', json_encode($_POST));
// 引入支付寶
vendor('Alipay.AlipayNotify','','.class.php');
$config=$config=C('ALIPAY_CONFIG');
$notify=new \AlipayNotify($config);
// 驗證支付數據
$status=$notify->verifyReturn();
if($status){
// 下面寫驗證通過的邏輯 比如說更改訂單狀態等等 $_GET['out_trade_no'] 為訂單號;
echo "alipay_return success";
//$this->success('支付成功',U('User/Order/index')); //正式上線跳轉到用戶訂單頁
}else{
echo "alipay_return failed";
//$this->success('支付失敗',U('User/Order/index')); //正式上線跳轉到用戶支付失敗頁
}
}
/**
* notify_url接收頁面
*/
public function alipay_notify(){
// 下面的file_put_contents是用來簡單查看異步發過來的數據 測試完可以刪除;
file_put_contents('./notify.txt', json_encode($_POST));
// 引入支付寶
vendor('Alipay.AlipayNotify','','.class.php');
$config=$config=C('ALIPAY_CONFIG');
$alipayNotify = new \AlipayNotify($config);
// 驗證支付數據
$verify_result = $alipayNotify->verifyNotify();
if($verify_result) {
echo "alipay_notify success";
// 下面寫驗證通過的邏輯 比如說更改訂單狀態等等 $_POST['out_trade_no'] 為訂單號;
}else {
echo "alipay_notify fail";
}
}
}
```
1、我們本地訪問 `http://tp3/Api/Alipay/alipay_return` 出現如下圖片內容,這證明我們的代碼是正確無誤的

2、我們本地訪問 `http://tp3/Api/Alipay/alipay_notify` 出現如下圖片內容,這證明我們的代碼是正確無誤的

好了,那現在我刪除 `return.txt` 和 `notify.txt` 文件,進行下一步操作!
## 正確回調里邊會有什么?
好了,上邊的步驟做完了,那么我們想知道,正確的回調里邊到底有哪些內容呢?我們利用這些內容能干什么?
我們在本地訪問 `http://tp3/` 支付完成后,

細心的同學會看到我們的根目錄下沒有產生 `return.txt` 和 `notify.txt` 文件,怎么回事兒呢?

急躁的同學一定會從前往后翻代碼,看看我哪里寫錯了,或者各種測試,在這里我可以負責任的告訴你,如果是上邊的代碼,你一點兒錯都沒有。
那為什么不顯示呢?原因很簡單,支付回調只有在 `正確的域名` 而且 `域名經過備案` 下才可以操作!
那我們接配置文件修改后傳到服務器看一看!
```
'notify_url' => 'http://www.sxqibo.com/Api/Alipay/alipay_notify', // 異步接收支付狀態通知的鏈接
'return_url' => 'http://www.sxqibo.com/Api/Alipay/alipay_return', // 頁面跳轉 同步通知 頁面路徑 支付寶處理完請求后,當前頁面自 動跳轉到商戶網站里指定頁面的 http 路徑。 (掃碼支付專用)
),
```
配置好了,上傳到`Linux`服務器上綁定并進行域名解析,給`Runtime`和`notify.txt`加上權限后,我們先直接訪問`http://www.sxqibo.com/Api/Alipay/alipay_notify`
## 正確得到回調
于是我們訪問 `http://www.sxqibo.com`,出現支付寶支付界面

支付跳轉頁

支付完成后,我們發現顯示成功回調!

**1、回調的網址如下:**
```
http://www.sxqibo.com/Api/Alipay/alipay_return?buyer_email=403236160%40qq.com&buyer_id=2088002654613928&exterface=create_direct_pay_by_user&is_success=T¬ify_id=RqPnCoPT3K9%252Fvwbh3Ih21yUF0iZ%252Bdom%252BJY%252B9FleN29SKwy8pn3k3VFzcWwfrOWxpbQtx¬ify_time=2017-09-16+10%3A51%3A03¬ify_type=trade_status_sync&out_trade_no=1505530197&payment_type=1&seller_email=sxqiboxx%40163.com&seller_id=2088821002087646&subject=%E6%B5%8B%E8%AF%95&total_fee=1.00&trade_no=2017091621001004920262044814&trade_status=TRADE_SUCCESS&sign=834aed06787b0718778df2297a93f0ac&sign_type=MD5
```
經過整理的網址如下:
```
http://www.sxqibo.com/Api/Alipay/alipay_return?
buyer_email=403236160%40qq.com&
uyer_id=2088002654613928&
exterface=create_direct_pay_by_user&
is_success=T&
notify_id=RqPnCoPT3K9%252Fvwbh3Ih21yUF0iZ%252Bdom%252BJY%252B9FleN29SKwy8pn3k3VFzcWwfrOWxpbQtx&
notify_time=2017-09-16+10%3A51%3A03&
notify_type=trade_status_sync&
out_trade_no=1505530197&
payment_type=1&
seller_email=sxqiboxx%40163.com&
seller_id=2088821002087646&
subject=%E6%B5%8B%E8%AF%95&
total_fee=1.00&
trade_no=2017091621001004920262044814&
trade_status=TRADE_SUCCESS&
sign=834aed06787b0718778df2297a93f0ac&
sign_type=MD5
```
很明顯,這個網址顯示的交易的一些基本信息,詳情請看[《電腦網站支付結果異步通知》](https://docs.open.alipay.com/270/105902/)
**2、我們到服務器上查看`return.txt`文件時**
這里是空的,很明顯,`alipay_return` 方法是用來回調顯示正確的頁面的!并且處理一些邏輯的,比如說修改訂單狀態,修改支付狀態,修改支付時間等等!
而 `alipay_notify` 方法是不管你關不關頁面!都會返回一些信息進行邏輯處理!處理方式和`alipay_return` 是一樣的!
**3、我們到服務器上查看`notify.txt`文件時**
多出了這么一段話:
```
{"discount":"0.00","payment_type":"1","trade_no":"2017091621001004920262044814","subject":"\u6d4b\u8bd5","buyer_email":"403***@qq.com","gmt_create":"2017-09-16 10:50:48","notify_type":"trade_status_sync","quantity":"1","out_trade_no":"1505530197","seller_id":"2088821002087646","notify_time":"2017-09-16 10:56:16","trade_status":"TRADE_SUCCESS","is_total_fee_adjust":"N","total_fee":"1.00","gmt_payment":"2017-09-16 10:50:53","seller_email":"sxqiboxx@163.com","price":"1.00","buyer_id":"2088002654613928","notify_id":"731fc19c26c728d5d46c198abb14234n3m","use_coupon":"N","sign_type":"MD5","sign":"632e0b36f2a59aed28a841120c084a3e"}root@iZ2ze855hjujym7drytfitZ:/data/wwwroot/www.sxqibo.com#
```
經過整理如下:
```
{
"discount": "0.00",
"payment_type": "1",
"trade_no": "2017091621001004920262044814",
"subject": "測試",
"buyer_email": "403***@qq.com",
"gmt_create": "2017-09-16 10:50:48",
"notify_type": "trade_status_sync",
"quantity": "1",
"out_trade_no": "1505530197",
"seller_id": "2088821002087646",
"notify_time": "2017-09-16 10:56:16",
"trade_status": "TRADE_SUCCESS",
"is_total_fee_adjust": "N",
"total_fee": "1.00",
"gmt_payment": "2017-09-16 10:50:53",
"seller_email": "sxqiboxx@163.com",
"price": "1.00",
"buyer_id": "2088002654613928",
"notify_id": "731fc19c26c728d5d46c198abb14234n3m",
"use_coupon": "N",
"sign_type": "MD5",
"sign": "632e0b36f2a59aed28a841120c084a3e"
}
```
很明顯,這個網址顯示的交易的一些基本信息,詳情請看[《支付寶return內容詳情分析》](https://docs.open.alipay.com/270/105902/)
## 回調的內容能做什么
很明顯,我們做支付的時候,幾分鐘全搞定,做回調的時候,卻寫了這么多!到現在還沒有寫完,
那我們用這些回的內容到底做什么呢?
一般來說,我們只需要更改支付狀態即可,將“未支付”更改為“已支付”即可!
但在實際復雜的邏輯業務中,并沒有這么簡單的!
比如我看支付寶的交易信息,查看什么時間交易的,哪個買家和我交易的,交易是否成功,交易創建時間,交易支付成功時間。當然還有其他相關信息,你