关于支付宝即时收款接口的对接过程,很简单,也有很多人发过,我这里就不在啰嗦了,对接完成后,在线支付成功后的回调,相对来说,是个难点,,我重点分享下我的经验。
我在开发二代旅游CMS()的时候,在回调的时候,也花了不少时间。
不管是支付宝接口好是微信支付接口,回调都分为跳转回调和异步通知回调,跳转回调是不保险的,加入客人支付完成后马上把支付页面关闭,没跳转,就通知不到你这个订单已经支付了,所以我们要用异步通知回调:
//首先设置介绍异步回调的地址
异步回调的具体处理函数,我这里也贴处理,供参考:
</span><span style="color: #800080;">$info</span>=M('rewrite')->where(<span style="color: #0000ff;">array</span>('name'=>'alipay'))-><span style="color: #000000;">find();
</span><span style="color: #800080;">$info</span>=json_decode(<span style="color: #800080;">$info</span>['content'],<span style="color: #0000ff;">true</span><span style="color: #000000;">);;
</span><span style="color: #008000;">//</span><span style="color: #008000;">↓↓↓↓↓↓↓↓↓↓请在这里配置您的基本信息↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
//合作身份者ID,签约账号,以2088开头由16位纯数字组成的字符串,查看地址:https://b.alipay.com/order/pidAndKey.htm
<span style="color: #800080;">$alipay_config['partner'] = <span style="color: #800080;">$info['alipay_pid'<span style="color: #000000;">]; <span style="color: #008000;">//<span style="color: #008000;">收款支付宝账号,以2088开头由16位纯数字组成的字符串,一般情况下收款账号就是签约账号
<span style="color: #800080;">$alipay_config['seller_id'] = <span style="color: #800080;">$info['alipay_pid'<span style="color: #000000;">]; <span style="color: #008000;">//<span style="color: #008000;"> MD5密钥,安全检验码,由数字和字母组成的32位字符串,查看地址:https://b.alipay.com/order/pidAndKey.htm
<span style="color: #800080;">$alipay_config['key'] = <span style="color: #800080;">$info['alipay_key'<span style="color: #000000;">];
<span style="color: #800080;">$ss=S('config'<span style="color: #000000;">);
<span style="color: #008000;">//<span style="color: #008000;"> 服务器异步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
<span style="color: #800080;">$alipay_config['notify_url'] = "".<span style="color: #800080;">$ss['web_url']."/v.PHP/Index-alipay_notify_url.html"<span style="color: #000000;">;
<span style="color: #008000;">//<span style="color: #008000;"> 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
<span style="color: #800080;">$alipay_config['return_url'] = "".<span style="color: #800080;">$ss['web_url']."/member.PHP"<span style="color: #000000;">;
<span style="color: #008000;">//<span style="color: #008000;">签名方式
<span style="color: #800080;">$alipay_config['sign_type'] = <span style="color: #008080;">strtoupper('MD5'<span style="color: #000000;">);
<span style="color: #008000;">//<span style="color: #008000;">字符编码格式 目前支持 gbk 或 utf-8
<span style="color: #800080;">$alipay_config['input_charset']= <span style="color: #008080;">strtolower('utf-8'<span style="color: #000000;">);
<span style="color: #008000;">//<span style="color: #008000;">ca证书路径地址,用于curl中ssl校验
//请保证cacert.pem文件在当前文件夹目录中
<span style="color: #800080;">$alipay_config['cacert'] = <span style="color: #008080;">getcwd().'\cacert.pem'<span style="color: #000000;">;
<span style="color: #008000;">//<span style="color: #008000;">访问模式,根据自己的服务器是否支持ssl访问,若支持请选择https;若不支持请选择http
<span style="color: #800080;">$alipay_config['transport'] = 'http'<span style="color: #000000;">;
<span style="color: #008000;">//<span style="color: #008000;"> 支付类型 ,无需修改
<span style="color: #800080;">$alipay_config['payment_type'] = "1"<span style="color: #000000;">;
<span style="color: #008000;">//<span style="color: #008000;"> 产品类型,无需修改
<span style="color: #800080;">$alipay_config['service'] = "create_direct_pay_by_user"<span style="color: #000000;">;
<span style="color: #008000;">//<span style="color: #008000;">↑↑↑↑↑↑↑↑↑↑请在这里配置您的基本信息↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
//↓↓↓↓↓↓↓↓↓↓ 请在这里配置防钓鱼信息,如果没开通防钓鱼功能,为空即可 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
// 防钓鱼时间戳 若要使用请调用类文件submit中的query_timestamp函数
<span style="color: #800080;">$alipay_config['anti_phishing_key'] = ""<span style="color: #000000;">;
<span style="color: #008000;">//<span style="color: #008000;"> 客户端的IP地址 非局域网的外网IP地址,如:221.0.0.1
<span style="color: #800080;">$alipay_config['exter_invoke_ip'] = ""<span style="color: #000000;">;
</span><span style="color: #800080;">$alipayNotify</span> = <span style="color: #0000ff;">new</span> \AlipayNotify(<span style="color: #800080;">$alipay_config</span><span style="color: #000000;">);
</span><span style="color: #800080;">$verify_result</span> = <span style="color: #800080;">$alipayNotify</span>-><span style="color: #000000;">verifyNotify();
</span><span style="color: #0000ff;">if</span>(<span style="color: #800080;">$verify_result</span>) {<span style="color: #008000;">//</span><span style="color: #008000;">验证成功</span>
<span style="color: #008000;">//</span><span style="color: #008000;">///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//请在这里<a href="/tag/jiashang/" target="_blank" class="keywords">加上</a>商户的业务逻辑程序代
//——请根据您的业务逻辑来编写程序(以下<a href="/tag/daima/" target="_blank" class="keywords">代码</a>仅作参考)——
//<a href="/tag/huoqu/" target="_blank" class="keywords">获取</a>支付宝的<a href="/tag/tongzhi/" target="_blank" class="keywords">通知</a>返回参数,可参考技术文档中服务器异步<a href="/tag/tongzhi/" target="_blank" class="keywords">通知</a>参数列表
//商户订单号</span>
<span style="color: #800080;">$out_trade_no</span> = <span style="color: #800080;">$_POST</span>['out_trade_no'<span style="color: #000000;">];
</span><span style="color: #008000;">//</span><span style="color: #008000;">支付宝交易号</span>
<span style="color: #800080;">$trade_no</span> = <span style="color: #800080;">$_POST</span>['trade_no'<span style="color: #000000;">];
</span><span style="color: #008000;">//</span><span style="color: #008000;">交易状态</span>
<span style="color: #800080;">$trade_status</span> = <span style="color: #800080;">$_POST</span>['trade_status'<span style="color: #000000;">];
</span><span style="color: #800080;">$total_fee</span>=<span style="color: #800080;">$_POST</span>['total_fee'<span style="color: #000000;">];
</span><span style="color: #008000;">//</span><span style="color: #008000;">if( $info['alipay_pid']!=$seller_id) return ''; //收款账户不一致</span>
<span style="color: #800080;">$info</span>=M('order')->where(<span style="color: #0000ff;">array</span>('no'=><span style="color: #800080;">$out_trade_no</span>))-><span style="color: #000000;">find();
</span><span style="color: #0000ff;">if</span>(!<span style="color: #800080;">$info</span>) <span style="color: #0000ff;">return</span> ''; <span style="color: #008000;">//</span><span style="color: #008000;">订单号不存在</span>
<span style="color: #0000ff;">if</span>(<span style="color: #800080;">$_POST</span>['trade_status'] == 'TRADE_FINISHED'<span style="color: #000000;">) {
</span><span style="color: #008000;">//</span><span style="color: #008000;">判断该笔订单是否在商户网站中已经做过处理
//如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
//请务必判断请求时的total_fee、seller_id与<a href="/tag/tongzhi/" target="_blank" class="keywords">通知</a>时<a href="/tag/huoqu/" target="_blank" class="keywords">获取</a>的total_fee、seller_id为一致的
//如果有做过处理,不执行商户的业务程序</span>
<span style="color: #800080;">$data</span>=''<span style="color: #000000;">;
</span><span style="color: #800080;">$data</span>['status']=2<span style="color: #000000;">;
</span><span style="color: #800080;">$data</span>['pay_price']=<span style="color: #800080;">$total_fee</span><span style="color: #000000;">;
</span><span style="color: #800080;">$data</span>['pay_type']='支付宝'<span style="color: #000000;">;
</span><span style="color: #800080;">$data</span>['buyer']=<span style="color: #800080;">$_POST</span>['buyer_email'<span style="color: #000000;">];
</span><span style="color: #800080;">$data</span>['trade_no']=<span style="color: #800080;">$trade_no</span><span style="color: #000000;">;
</span><span style="color: #800080;">$data</span>['pay_time']=<span style="color: #008080;">time</span><span style="color: #000000;">();
M(</span>'order')->where(<span style="color: #0000ff;">array</span>('no'=><span style="color: #800080;">$out_trade_no</span>))->save(<span style="color: #800080;">$data</span><span style="color: #000000;">);
</span><span style="color: #800080;">$c</span>=M('smtp_templates')->where(<span style="color: #0000ff;">array</span>('id'=>5))-><span style="color: #000000;">find();
</span><span style="color: #0000ff;">if</span>(<span style="color: #800080;">$c</span>['status']==1<span style="color: #000000;">)
{
</span><span style="color: #800080;">$content</span> = <span style="color: #008080;">str_replace</span>('{title}',<span style="color: #800080;">$info</span>['goods_name'],<span style="color: #800080;">$c</span>['content'<span style="color: #000000;">]);
</span><span style="color: #800080;">$content</span> = <span style="color: #008080;">str_replace</span>('{id}',<span style="color: #800080;">$info</span>['goods_id'],<span style="color: #800080;">$content</span><span style="color: #000000;">);
</span><span style="color: #800080;">$content</span> = <span style="color: #008080;">str_replace</span>('{price}',<span style="color: #800080;">$total_fee</span>,<span style="color: #800080;">$content</span><span style="color: #000000;">);
</span><span style="color: #800080;">$content</span> = <span style="color: #008080;">str_replace</span>('{time}',<span style="color: #008080;">date</span>('Y-m-d H:i:s',<span style="color: #008080;">time</span>()),<span style="color: #800080;">$content</span><span style="color: #000000;">);
</span><span style="color: #800080;">$c</span>=M('email_note')->where(<span style="color: #0000ff;">array</span>('pay_id'=><span style="color: #800080;">$out_trade_no</span>))-><span style="color: #000000;">find();
</span><span style="color: #0000ff;">if</span>(!<span style="color: #800080;">$c</span><span style="color: #000000;">)
{
</span><span style="color: #800080;">$e</span>=''<span style="color: #000000;">;
</span><span style="color: #800080;">$e</span>['email']=<span style="color: #800080;">$info</span>['c_email'<span style="color: #000000;">];
</span><span style="color: #800080;">$e</span>['content']=<span style="color: #800080;">$content</span><span style="color: #000000;">;
</span><span style="color: #800080;">$e</span>['pay_id']=<span style="color: #800080;">$out_trade_no</span><span style="color: #000000;">;
M(</span>'email_note')->add(<span style="color: #800080;">$e</span><span style="color: #000000;">);
</span><span style="color: #800080;">$m</span>=<span style="color: #008080;">explode</span>('|',<span style="color: #800080;">$c</span>['ather'<span style="color: #000000;">]);
</span><span style="color: #0000ff;">foreach</span>(<span style="color: #800080;">$m</span> <span style="color: #0000ff;">as</span> <span style="color: #800080;">$mail</span><span style="color: #000000;">)
{
</span><span style="color: #0000ff;">if</span>(validate_email(<span style="color: #800080;">$mail</span><span style="color: #000000;">))
{
</span><span style="color: #800080;">$e</span>['email']=<span style="color: #800080;">$mail</span><span style="color: #000000;">;
M(</span>'email_note')->add(<span style="color: #800080;">$e</span><span style="color: #000000;">);
}
}
}
}
</span><span style="color: #008000;">//</span><span style="color: #008000;">注意:
//退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态<a href="/tag/tongzhi/" target="_blank" class="keywords">通知</a>
//调试用,写文本<a href="/tag/hanshu/" target="_blank" class="keywords">函数</a>记录程序运行情况是否正常
//logResult("这里写入想要调试的<a href="/tag/daima/" target="_blank" class="keywords">代码</a>变量值,或其他运行的结果记录");</span>
<span style="color: #000000;"> }
<span style="color: #0000ff;">else <span style="color: #0000ff;">if (<span style="color: #800080;">$_POST['trade_status'] == 'TRADE_SUCCESS'<span style="color: #000000;">) {
<span style="color: #008000;">//<span style="color: #008000;">判断该笔订单是否在商户网站中已经做过处理
//如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
//请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的
//如果有做过处理,不执行商户的业务程序
<span style="color: #800080;">$data</span>=''<span style="color: #000000;">;
</span><span style="color: #800080;">$data</span>['status']=2<span style="color: #000000;">;
</span><span style="color: #800080;">$data</span>['pay_price']=<span style="color: #800080;">$total_fee</span><span style="color: #000000;">;
</span><span style="color: #800080;">$data</span>['pay_type']='支付宝'<span style="color: #000000;">;
</span><span style="color: #800080;">$data</span>['buyer']=<span style="color: #800080;">$_POST</span>['buyer_email'<span style="color: #000000;">];
</span><span style="color: #800080;">$data</span>['trade_no']=<span style="color: #800080;">$trade_no</span><span style="color: #000000;">;
</span><span style="color: #800080;">$data</span>['pay_time']=<span style="color: #008080;">time</span><span style="color: #000000;">();
M(</span>'order')->where(<span style="color: #0000ff;">array</span>('no'=><span style="color: #800080;">$out_trade_no</span>))->save(<span style="color: #800080;">$data</span><span style="color: #000000;">);
</span><span style="color: #800080;">$c</span>=M('smtp_templates')->where(<span style="color: #0000ff;">array</span>('id'=>5))-><span style="color: #000000;">find();
</span><span style="color: #0000ff;">if</span>(<span style="color: #800080;">$c</span>['status']==1<span style="color: #000000;">)
{
</span><span style="color: #800080;">$content</span> = <span style="color: #008080;">str_replace</span>('{title}',<span style="color: #800080;">$c</span>['ather'<span style="color: #000000;">]);
</span><span style="color: #0000ff;">foreach</span>(<span style="color: #800080;">$m</span> <span style="color: #0000ff;">as</span> <span style="color: #800080;">$mail</span><span style="color: #000000;">)
{
</span><span style="color: #0000ff;">if</span>(validate_email(<span style="color: #800080;">$mail</span><span style="color: #000000;">))
{
</span><span style="color: #800080;">$e</span>['email']=<span style="color: #800080;">$mail</span><span style="color: #000000;">;
M(</span>'email_note')->add(<span style="color: #800080;">$e</span><span style="color: #000000;">);
}
}
}
}
</span><span style="color: #008000;">//</span><span style="color: #008000;">注意:
//付款完成后,支付宝系统发送该交易状态<a href="/tag/tongzhi/" target="_blank" class="keywords">通知</a>
//调试用,写文本<a href="/tag/hanshu/" target="_blank" class="keywords">函数</a>记录程序运行情况是否正常
//logResult("这里写入想要调试的<a href="/tag/daima/" target="_blank" class="keywords">代码</a>变量值,或其他运行的结果记录");</span>
<span style="color: #000000;"> }
</span><span style="color: #008000;">//</span><span style="color: #008000;">——请根据您的业务逻辑来编写程序(以上<a href="/tag/daima/" target="_blank" class="keywords">代码</a>仅作参考)——</span>
<span style="color: #0000ff;">echo</span> "success"; <span style="color: #008000;">//</span><span style="color: #008000;">请不要<a href="/tag/xiugai/" target="_blank" class="keywords">修改</a>或<a href="/tag/shanchu/" target="_blank" class="keywords">删除</a></span>
<span style="color: #008000;">//</span><span style="color: #008000;">///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////</span>
<span style="color: #000000;">}
<span style="color: #0000ff;">else<span style="color: #000000;"> {
<span style="color: #008000;">//<span style="color: #008000;">验证失败
<span style="color: #0000ff;">echo "fail"<span style="color: #000000;">;
</span><span style="color: #008000;">//</span><span style="color: #008000;">调试用,写文本<a href="/tag/hanshu/" target="_blank" class="keywords">函数</a>记录程序运行情况是否正常
//logResult("这里写入想要调试的<a href="/tag/daima/" target="_blank" class="keywords">代码</a>变量值,或其他运行的结果记录");</span>
<span style="color: #000000;">}
}
因为是异步通知,所以调试是个麻烦事,不能所见即所得,也就是说,一般情况下没办法echo或者print_r打印输出结果,没办法知道他执行到哪里或者执行结果,这个时候,我们就用到log文件输出,代码:
以上代码会在根目录下自动生成一个log.txt的文件,这样,就可以轻松知道执行结果,方便调试了
支付宝的异步通知接口,会多次通知,直到你返回success为止,也就是说,你提交一个测试订单,可以测试很多次,因为你没有返回success的话,他会每隔一定时间,通知一次