[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` 出现如下图片内容,这证明我们的代码是正确无误的
![mark](http://qiniu.newthink.cc/blog/20170916-094748773.png)
2、我们本地访问 `http://tp3/Api/Alipay/alipay_notify` 出现如下图片内容,这证明我们的代码是正确无误的
![mark](http://qiniu.newthink.cc/blog/20170916-094837855.png)
好了,那现在我删除 `return.txt` 和 `notify.txt` 文件,进行下一步操作!
## 正确回调里边会有什么?
好了,上边的步骤做完了,那么我们想知道,正确的回调里边到底有哪些内容呢?我们利用这些内容能干什么?
我们在本地访问 `http://tp3/` 支付完成后,
![mark](http://qiniu.newthink.cc/blog/20170916-094837855.png)
细心的同学会看到我们的根目录下没有产生 `return.txt` 和 `notify.txt` 文件,怎么回事儿呢?
![mark](http://qiniu.newthink.cc/blog/20170916-095134582.png)
急躁的同学一定会从前往后翻代码,看看我哪里写错了,或者各种测试,在这里我可以负责任的告诉你,如果是上边的代码,你一点儿错都没有。
那为什么不显示呢?原因很简单,支付回调只有在 `正确的域名` 而且 `域名经过备案` 下才可以操作!
那我们接配置文件修改后传到服务器看一看!
```
'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`,出现支付宝支付界面
![mark](http://qiniu.newthink.cc/blog/20170916-104700296.png)
支付跳转页
![mark](http://qiniu.newthink.cc/blog/20170916-105202752.png)
支付完成后,我们发现显示成功回调!
![mark](http://qiniu.newthink.cc/blog/20170916-105232915.png)
**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/)
## 回调的内容能做什么
很明显,我们做支付的时候,几分钟全搞定,做回调的时候,却写了这么多!到现在还没有写完,
那我们用这些回的内容到底做什么呢?
一般来说,我们只需要更改支付状态即可,将“未支付”更改为“已支付”即可!
但在实际复杂的逻辑业务中,并没有这么简单的!
比如我看支付宝的交易信息,查看什么时间交易的,哪个买家和我交易的,交易是否成功,交易创建时间,交易支付成功时间。当然还有其他相关信息,你