本文实例讲述了thinkPHP框架对接支付宝即时到账接口回调操作。分享给大家供大家参考,具体如下:
关于支付宝即时收款接口的对接过程,很简单,也有很多人发过,我这里就不在啰嗦了,对接完成后,在线支付成功后的回调,相对来说,是个难点,,我重点分享下我的经验。
我在开发二代旅游CMS(http://www.erdaicms.com)的时候,在回调的时候,也花了不少时间。
不管是支付宝接口好是微信支付接口,回调都分为跳转回调和异步通知回调,跳转回调是不保险的,加入客人支付完成后马上把支付页面关闭,没跳转,就通知不到你这个订单已经支付了,所以我们要用异步通知回调:
复制代码 代码如下:
$alipay_config['notify_url'] = "".$ss['web_url']."/v.php/Index-alipay_notify_url.html";
首先设置介绍异步回调的地址
异步回调的具体处理函数,我这里也贴处理,供参考:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
/* 支付宝异步通知*/ public function alipay_notify_url() { vendor( 'Alipay.Corefunction' ); vendor( 'Alipay.Md5function' ); vendor( 'Alipay.Notify' ); vendor( 'Alipay.Submit' ); $info =M( 'rewrite' )->where( array ( 'name' => 'alipay' ))->find(); $info =json_decode( $info [ 'content' ],true);; //↓↓↓↓↓↓↓↓↓↓请在这里配置您的基本信息↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ //合作身份者ID,签约账号,以2088开头由16位纯数字组成的字符串,查看地址:https://b.alipay.com/order/pidAndKey.htm $alipay_config [ 'partner' ] = $info [ 'alipay_pid' ]; //收款支付宝账号,以2088开头由16位纯数字组成的字符串,一般情况下收款账号就是签约账号 $alipay_config [ 'seller_id' ] = $info [ 'alipay_pid' ]; // MD5密钥,安全检验码,由数字和字母组成的32位字符串,查看地址:https://b.alipay.com/order/pidAndKey.htm $alipay_config [ 'key' ] = $info [ 'alipay_key' ]; $ss =S( 'config' ); // 服务器异步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 $alipay_config [ 'notify_url' ] = "" . $ss [ 'web_url' ]. "/v.php/Index-alipay_notify_url.html" ; // 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 $alipay_config [ 'return_url' ] = "" . $ss [ 'web_url' ]. "/member.php" ; //签名方式 $alipay_config [ 'sign_type' ] = strtoupper ( 'MD5' ); //字符编码格式 目前支持 gbk 或 utf-8 $alipay_config [ 'input_charset' ]= strtolower ( 'utf-8' ); //ca证书路径地址,用于curl中ssl校验 //请保证cacert.pem文件在当前文件夹目录中 $alipay_config [ 'cacert' ] = getcwd (). '\\cacert.pem' ; //访问模式,根据自己的服务器是否支持ssl访问,若支持请选择https;若不支持请选择http $alipay_config [ 'transport' ] = 'http' ; // 支付类型 ,无需修改 $alipay_config [ 'payment_type' ] = "1" ; // 产品类型,无需修改 $alipay_config [ 'service' ] = "create_direct_pay_by_user" ; //↑↑↑↑↑↑↑↑↑↑请在这里配置您的基本信息↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ //↓↓↓↓↓↓↓↓↓↓ 请在这里配置防钓鱼信息,如果没开通防钓鱼功能,为空即可 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ // 防钓鱼时间戳 若要使用请调用类文件submit中的query_timestamp函数 $alipay_config [ 'anti_phishing_key' ] = "" ; // 客户端的IP地址 非局域网的外网IP地址,如:221.0.0.1 $alipay_config [ 'exter_invoke_ip' ] = "" ; $alipayNotify = new \AlipayNotify( $alipay_config ); $verify_result = $alipayNotify ->verifyNotify(); if ( $verify_result ) { //验证成功 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //请在这里加上商户的业务逻辑程序代 //——请根据您的业务逻辑来编写程序(以下代码仅作参考)—— //获取支付宝的通知返回参数,可参考技术文档中服务器异步通知参数列表 //商户订单号 $out_trade_no = $_POST [ 'out_trade_no' ]; //支付宝交易号 $trade_no = $_POST [ 'trade_no' ]; //交易状态 $trade_status = $_POST [ 'trade_status' ]; $total_fee = $_POST [ 'total_fee' ]; //if( $info['alipay_pid']!=$seller_id) return ''; //收款账户不一致 $info =M( 'order' )->where( array ( 'no' => $out_trade_no ))->find(); if (! $info ) return '' ; //订单号不存在 if ( $_POST [ 'trade_status' ] == 'TRADE_FINISHED' ) { //判断该笔订单是否在商户网站中已经做过处理 //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 //请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的 //如果有做过处理,不执行商户的业务程序 $data = '' ; $data [ 'status' ]=2; $data [ 'pay_price' ]= $total_fee ; $data [ 'pay_type' ]= '支付宝' ; $data [ 'buyer' ]= $_POST [ 'buyer_email' ]; $data [ 'trade_no' ]= $trade_no ; $data [ 'pay_time' ]=time(); M( 'order' )->where( array ( 'no' => $out_trade_no ))->save( $data ); $c =M( 'smtp_templates' )->where( array ( 'id' =>5))->find(); if ( $c [ 'status' ]==1) { $content = str_replace ( '{title}' , $info [ 'goods_name' ], $c [ 'content' ]); $content = str_replace ( '{id}' , $info [ 'goods_id' ], $content ); $content = str_replace ( '{price}' , $total_fee , $content ); $content = str_replace ( '{time}' , date ( 'Y-m-d H:i:s' ,time()), $content ); $c =M( 'email_note' )->where( array ( 'pay_id' => $out_trade_no ))->find(); if (! $c ) { $e = '' ; $e [ 'email' ]= $info [ 'c_email' ]; $e [ 'content' ]= $content ; $e [ 'pay_id' ]= $out_trade_no ; M( 'email_note' )->add( $e ); $m = explode ( '|' , $c [ 'ather' ]); foreach ( $m as $mail ) { if (validate_email( $mail )) { $e [ 'email' ]= $mail ; M( 'email_note' )->add( $e ); } } } } //注意: //退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知 //调试用,写文本函数记录程序运行情况是否正常 //logResult("这里写入想要调试的代码变量值,或其他运行的结果记录"); } else if ( $_POST [ 'trade_status' ] == 'TRADE_SUCCESS' ) { //判断该笔订单是否在商户网站中已经做过处理 //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 //请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的 //如果有做过处理,不执行商户的业务程序 $data = '' ; $data [ 'status' ]=2; $data [ 'pay_price' ]= $total_fee ; $data [ 'pay_type' ]= '支付宝' ; $data [ 'buyer' ]= $_POST [ 'buyer_email' ]; $data [ 'trade_no' ]= $trade_no ; $data [ 'pay_time' ]=time(); M( 'order' )->where( array ( 'no' => $out_trade_no ))->save( $data ); $c =M( 'smtp_templates' )->where( array ( 'id' =>5))->find(); if ( $c [ 'status' ]==1) { $content = str_replace ( '{title}' , $info [ 'goods_name' ], $c [ 'content' ]); $content = str_replace ( '{id}' , $info [ 'goods_id' ], $content ); $content = str_replace ( '{price}' , $total_fee , $content ); $content = str_replace ( '{time}' , date ( 'Y-m-d H:i:s' ,time()), $content ); $c =M( 'email_note' )->where( array ( 'pay_id' => $out_trade_no ))->find(); if (! $c ) { $e = '' ; $e [ 'email' ]= $info [ 'c_email' ]; $e [ 'content' ]= $content ; $e [ 'pay_id' ]= $out_trade_no ; M( 'email_note' )->add( $e ); $m = explode ( '|' , $c [ 'ather' ]); foreach ( $m as $mail ) { if (validate_email( $mail )) { $e [ 'email' ]= $mail ; M( 'email_note' )->add( $e ); } } } } //注意: //付款完成后,支付宝系统发送该交易状态通知 //调试用,写文本函数记录程序运行情况是否正常 //logResult("这里写入想要调试的代码变量值,或其他运行的结果记录"); } //——请根据您的业务逻辑来编写程序(以上代码仅作参考)—— echo "success" ; //请不要修改或删除 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// } else { //验证失败 echo "fail" ; //调试用,写文本函数记录程序运行情况是否正常 //logResult("这里写入想要调试的代码变量值,或其他运行的结果记录"); } } |
因为是异步通知,所以调试是个麻烦事,不能所见即所得,也就是说,一般情况下没办法echo或者print_r打印输出结果,没办法知道他执行到哪里或者执行结果,这个时候,我们就用到log文件输出,代码:
1
2
3
|
$file = './log.txt' ; //要写入文件的文件名(可以是任意文件名),如果文件不存在,将会创建一个 $content = "支付成功" . $bdata [ 'total_fee' ]. "\n" ; //要写入的内容 file_put_contents ( $file , $content ,FILE_APPEND); //写入文件 |
以上代码会在根目录下自动生成一个log.txt的文件,这样,就可以轻松知道执行结果,方便调试了
支付宝的异步通知接口,会多次通知,直到你返回success为止,也就是说,你提交一个测试订单,可以测试很多次,因为你没有返回success的话,他会每隔一定时间,通知一次
希望本文所述对大家基于ThinkPHP框架的PHP程序设计有所帮助。