Authored by 郝肖肖

支付成功签名验证

@@ -217,4 +217,24 @@ class OrderData @@ -217,4 +217,24 @@ class OrderData
217 return Yohobuy::get(Yohobuy::API_URL, $param); 217 return Yohobuy::get(Yohobuy::API_URL, $param);
218 } 218 }
219 219
  220 + /**
  221 + * 支付成功后--支付确认接口
  222 + * @param type int $orderCode 订单号
  223 + * @param type int $paymentId 支付方式
  224 + * @param type int $uid 用户ID
  225 + * @return type []
  226 + */
  227 + public static function payConfirm($orderCode, $paymentId, $uid)
  228 + {
  229 + // 构建必传参数
  230 + $param = Yohobuy::param();
  231 + $param['method'] = 'app.SpaceOrders.payConfirm';
  232 + $param['order_code'] = $orderCode;
  233 + $param['payment_id'] = $paymentId;
  234 + $param['uid'] = intval($uid);
  235 + $param['client_secret'] = Sign::getSign($param);
  236 +
  237 + // 调用接口获得数据
  238 + return Yohobuy::post(Yohobuy::API_URL, $param);
  239 + }
220 } 240 }
@@ -7,7 +7,7 @@ use Plugin\Pay\aliwap\AliwapReqparams; @@ -7,7 +7,7 @@ use Plugin\Pay\aliwap\AliwapReqparams;
7 use Plugin\Pay\aliwap\AliwapRspparams; 7 use Plugin\Pay\aliwap\AliwapRspparams;
8 use Api\Yohobuy; 8 use Api\Yohobuy;
9 use Plugin\Helpers; 9 use Plugin\Helpers;
10 - 10 +use Plugin\UdpLog;
11 /** 11 /**
12 * 支付宝手机网页支付 12 * 支付宝手机网页支付
13 */ 13 */
@@ -21,20 +21,6 @@ class AliwapService @@ -21,20 +21,6 @@ class AliwapService
21 { 21 {
22 $this->logProjectPrefix = 'aliwap'; 22 $this->logProjectPrefix = 'aliwap';
23 $this->config = new AliwapConfig(); 23 $this->config = new AliwapConfig();
24 -  
25 - $this->alipay_config = array(  
26 - 'partner' => $this->config->partner,  
27 - 'key' => $this->config->alipay_key,  
28 - 'sign_type' => 'MD5',  
29 - 'input_charset' => 'utf-8',  
30 - 'cacert' => dirname(__FILE__) . '/cacert.pem',  
31 - 'transport' => 'http'  
32 - );  
33 - require_once("lib/alipay_core.function.php");  
34 - require_once("lib/alipay_rsa.function.php");  
35 - require_once("lib/alipay_md5.function.php");  
36 - require_once("lib/alipay_notify.class.php");  
37 - require_once("lib/alipay_submit.class.php");  
38 } 24 }
39 25
40 /** 26 /**
@@ -87,64 +73,60 @@ class AliwapService @@ -87,64 +73,60 @@ class AliwapService
87 /** 73 /**
88 * 解析结果 74 * 解析结果
89 * 75 *
90 - * @see AliwapInterface::parseResponse()  
91 */ 76 */
92 public function parseResponse(Array $arrResponse) 77 public function parseResponse(Array $arrResponse)
93 { 78 {
  79 + UdpLog::info("【{$this->logProjectPrefix}-支付宝支付】,function:parseResponse,回调参数", $arrResponse);
  80 + if (isset($arrResponse['q'])) {
  81 + unset($arrResponse['q']);
  82 + }
94 $rsp = new AliwapRspparams(); 83 $rsp = new AliwapRspparams();
95 - if ($arrResponse['type'] == 'return') {  
96 - //return 返回  
97 - $alipayNotify = new \AlipayNotify($this->alipay_config);  
98 - $verify_result = $alipayNotify->verifyReturn();  
99 - if ($verify_result) {  
100 - //商户订单号  
101 - $rsp->orderCode = $_GET['out_trade_no'];  
102 - $rsp->payResult = 200;  
103 - //支付宝交易号  
104 - $trade_no = $_GET['trade_no'];  
105 - } else {  
106 - $rsp->payResult = 400;  
107 - } 84 + if (!$this->checkResponse($arrResponse)) {
  85 + //验证不成功
  86 + $rsp->payResult = -1;
108 } else { 87 } else {
109 - //服务器返回  
110 - $alipayNotify = new \AlipayNotify($this->alipay_config);  
111 - $verify_result = $alipayNotify->verifyNotify();  
112 - if ($verify_result) {  
113 - //解密(如果是RSA签名需要解密,如果是MD5签名则下面一行清注释掉)  
114 - // $notify_data = $alipayNotify->decrypt($_POST['notify_data']);  
115 - //解析notify_data  
116 - //注意:该功能PHP5环境及以上支持,需开通curl、SSL等PHP配置环境。建议本地调试时使用PHP开发软件  
117 - $doc = new \DOMDocument();  
118 - $doc->loadXML($_POST['notify_data']);  
119 - if (!empty($doc->getElementsByTagName("notify")->item(0)->nodeValue)) {  
120 - //商户订单号  
121 - $out_trade_no = $doc->getElementsByTagName("out_trade_no")->item(0)->nodeValue;  
122 - //支付宝交易号  
123 - $trade_no = $doc->getElementsByTagName("trade_no")->item(0)->nodeValue;  
124 - //交易状态  
125 - $trade_status = $doc->getElementsByTagName("trade_status")->item(0)->nodeValue;  
126 - if ($trade_status == 'TRADE_FINISHED' || $trade_status == 'TRADE_SUCCESS') {  
127 - $rsp->orderCode = $out_trade_no;  
128 - $rsp->payResult = 200;  
129 - } else {  
130 - $rsp->payResult = 400;  
131 - }  
132 - }  
133 - } else {  
134 - $rsp->payResult = 401;  
135 - } 88 + $rsp->bankName = "";
  89 + $outTradeNo = $arrResponse["out_trade_no"];
  90 + $rsp->orderCode = $outTradeNo;
  91 + $rsp->payResult = $this->convertResult($arrResponse["trade_status"]);
  92 + $rsp->payTime = isset($arrResponse["gmt_payment"]) ? $arrResponse["gmt_payment"] : '';
  93 + $rsp->totalFee = $arrResponse["total_fee"];
  94 + $rsp->resultMsg = $arrResponse["notify_type"];
  95 + //添加支付订单号和交易号
  96 + $rsp->payOrderCode = $outTradeNo;
  97 + $rsp->tradeNo = $arrResponse['trade_no'];
  98 + $rsp->bankBillNo = "";
136 } 99 }
  100 +
  101 + UdpLog::info("【{$this->logProjectPrefix}-支付宝支付】,function:parseResponse,回调参数的结果", $arrResponse);
137 return $rsp; 102 return $rsp;
138 } 103 }
139 104
140 - private function getTokenReqData($out_trade_no, $subject, $total_fee) 105 + protected function convertResult($resultCode)
141 { 106 {
142 - return '<direct_trade_create_req><notify_url>' . $this->config->notify_url .  
143 - '</notify_url><call_back_url>' . $this->config->return_url .  
144 - '</call_back_url><seller_account_name>' . $this->config->sellerMail .  
145 - '</seller_account_name><out_trade_no>' . $out_trade_no . '</out_trade_no><subject>' . 'yoho order:' . $out_trade_no .  
146 - '</subject><total_fee>' . $total_fee . '</total_fee><merchant_url>' . $this->config->merchant_url . $out_trade_no .  
147 - '</merchant_url></direct_trade_create_req>'; 107 + if ($resultCode == "TRADE_SUCCESS") {
  108 + return 200;
  109 + }
  110 + return 400;
148 } 111 }
  112 +
  113 + /**
  114 + * 验证回复的正确性
  115 + * @see QPay_Utils_Abstract::verifResponse()
  116 + */
  117 + protected function checkResponse(array $arrResponse)
  118 + {
  119 + ksort($arrResponse);
  120 + reset($arrResponse);
  121 + $sign = '';
  122 + foreach ($arrResponse AS $key => $val) {
  123 + if ($key === 'sign' || $key === 'sign_type' || $key === 'code' || $val === '') {
  124 + continue;
  125 + }
  126 + $sign .= "$key=$val&";
  127 + }
  128 + $sign = substr($sign, 0, -1) . $this->config->alipay_key;
149 129
  130 + return md5($sign) != $arrResponse['sign'] ? false : true;
  131 + }
150 } 132 }
1 -<?php  
2 -  
3 -/**  
4 - * 支付配置  
5 - *  
6 - * @name AliwapConfig  
7 - * @package Plugin\Pay\aliwap\v303  
8 - * @copyright yoho.inc  
9 - * @version 1.0 (2016-1-25 19:39:30)  
10 - * @author fei.hong <fei.hong@yoho.cn>  
11 - */  
12 -return array(  
13 - 'pay_url' => 'https://mapi.alipay.com/gateway.do?',  
14 - // 支付宝的用户ID  
15 - 'partner' => '2088701661478015',  
16 - // 收款支付宝账号  
17 - 'seller_id' => '2088701661478015',  
18 - // 编码  
19 - 'input_charset' => 'utf-8',  
20 - // 支付类型  
21 - 'payment_type' => '1',  
22 - // 通知url  
23 - 'notify_url' => 'http://testservice.yoho.cn:28077/payment/alipaywap_notify', //'http://m.yohobuy.com/shopping/pay/aliwapnotice'  
24 - // 回调url  
25 - 'return_url' => 'http://m.yohobuy.com/shopping/pay/aliwapreturn',  
26 - // DSA、RSA、MD5三个值可选,必须大写  
27 - 'sign_type' => 'MD5',  
28 - // MD5签名对应的KEY  
29 - 'key' => 'kcxawi9bb07mzh0aq2wcirsf9znusobw',  
30 - // 访问模式,根据自己的服务器是否支持ssl访问,若支持请选择https;若不支持请选择http  
31 - 'transport' => 'http',  
32 - // ca证书路径地址,用于curl中ssl校验  
33 - 'cacert' => 'cacert.pem',  
34 -);  
1 -<?php  
2 -  
3 -namespace Plugin\Pay\aliwap\v303;  
4 -  
5 -/**  
6 - * 支付宝手机网页支付  
7 - */  
8 -class AliwapService  
9 -{  
10 -  
11 - var $config;  
12 - var $alipay_config;  
13 -  
14 - public function __construct()  
15 - {  
16 - $this->config = require(dirname(__FILE__) . '/AliwapConfig.php');  
17 -  
18 - require_once(dirname(__FILE__) . '/lib/alipay_submit.class.php');  
19 - }  
20 -  
21 - /**  
22 - * 构造请求参数  
23 - * @see QPay_Utils_Interface::getPayRequestPars()  
24 - */  
25 - public function getResponse($params)  
26 - {  
27 - $this->config['cacert'] = dirname(__FILE__) . '/cacert.pem';  
28 -  
29 - //构造要请求的参数数组,无需改动  
30 - $parameter = array(  
31 - "service" => 'alipay.wap.create.direct.pay.by.user',  
32 - "partner" => $this->config['partner'],  
33 - "seller_id" => $this->config['seller_id'],  
34 - "payment_type" => $this->config['payment_type'],  
35 - "notify_url" => $this->config['notify_url'],  
36 - "return_url" => $this->config['return_url'],  
37 - "out_trade_no" => date('Ymdhis') . $params['orderCode'],  
38 - "subject" => 'yoho order:' . $params['orderCode'],  
39 - "total_fee" => $params['totalFee'],  
40 - "show_url" => $params['showUrl'],  
41 - "body" => '有货订单号:' . $params['orderCode'],  
42 - "it_b_pay" => $params['payExpire'],  
43 - "_input_charset" => $this->config['input_charset'],  
44 - );  
45 -  
46 - //建立请求  
47 - $alipaySubmit = new \AlipaySubmit($this->config);  
48 - $para = $alipaySubmit->buildRequestHttp($parameter);  
49 - var_dump($para);  
50 - }  
51 -  
52 -}  
This diff could not be displayed because it is too large.
1 -<?php  
2 -  
3 -/* *  
4 - * 支付宝接口公用函数  
5 - * 详细:该类是请求、通知返回两个文件所调用的公用函数核心处理文件  
6 - * 版本:3.3  
7 - * 日期:2012-07-19  
8 - * 说明:  
9 - * 以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。  
10 - * 该代码仅供学习和研究支付宝接口使用,只是提供一个参考。  
11 - */  
12 -  
13 -/**  
14 - * 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串  
15 - * @param $para 需要拼接的数组  
16 - * return 拼接完成以后的字符串  
17 - */  
18 -function createLinkstring($para)  
19 -{  
20 - $arg = "";  
21 - while (list ($key, $val) = each($para)) {  
22 - $arg.=$key . "=" . $val . "&";  
23 - }  
24 - //去掉最后一个&字符  
25 - $arg = substr($arg, 0, count($arg) - 2);  
26 -  
27 - //如果存在转义字符,那么去掉转义  
28 - if (get_magic_quotes_gpc()) {  
29 - $arg = stripslashes($arg);  
30 - }  
31 -  
32 - return $arg;  
33 -}  
34 -  
35 -/**  
36 - * 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串,并对字符串做urlencode编码  
37 - * @param $para 需要拼接的数组  
38 - * return 拼接完成以后的字符串  
39 - */  
40 -function createLinkstringUrlencode($para)  
41 -{  
42 - $arg = "";  
43 - while (list ($key, $val) = each($para)) {  
44 - $arg.=$key . "=" . urlencode($val) . "&";  
45 - }  
46 - //去掉最后一个&字符  
47 - $arg = substr($arg, 0, count($arg) - 2);  
48 -  
49 - //如果存在转义字符,那么去掉转义  
50 - if (get_magic_quotes_gpc()) {  
51 - $arg = stripslashes($arg);  
52 - }  
53 -  
54 - return $arg;  
55 -}  
56 -  
57 -/**  
58 - * 除去数组中的空值和签名参数  
59 - * @param $para 签名参数组  
60 - * return 去掉空值与签名参数后的新签名参数组  
61 - */  
62 -function paraFilter($para)  
63 -{  
64 - $para_filter = array();  
65 - while (list ($key, $val) = each($para)) {  
66 - if ($key == "sign" || $key == "sign_type" || $val == "")  
67 - continue;  
68 - else  
69 - $para_filter[$key] = $para[$key];  
70 - }  
71 - return $para_filter;  
72 -}  
73 -  
74 -/**  
75 - * 对数组排序  
76 - * @param $para 排序前的数组  
77 - * return 排序后的数组  
78 - */  
79 -function argSort($para)  
80 -{  
81 - ksort($para);  
82 - reset($para);  
83 - return $para;  
84 -}  
85 -  
86 -/**  
87 - * 写日志,方便测试(看网站需求,也可以改成把记录存入数据库)  
88 - * 注意:服务器需要开通fopen配置  
89 - * @param $word 要写入日志里的文本内容 默认值:空值  
90 - */  
91 -function logResult($word = '')  
92 -{  
93 - $fp = fopen("log.txt", "a");  
94 - flock($fp, LOCK_EX);  
95 - fwrite($fp, "执行日期:" . strftime("%Y%m%d%H%M%S", time()) . "\n" . $word . "\n");  
96 - flock($fp, LOCK_UN);  
97 - fclose($fp);  
98 -}  
99 -  
100 -/**  
101 - * 远程获取数据,POST模式  
102 - * 注意:  
103 - * 1.使用Crul需要修改服务器中php.ini文件的设置,找到php_curl.dll去掉前面的";"就行了  
104 - * 2.文件夹中cacert.pem是SSL证书请保证其路径有效,目前默认路径是:getcwd().'\\cacert.pem'  
105 - * @param $url 指定URL完整路径地址  
106 - * @param $cacert_url 指定当前工作目录绝对路径  
107 - * @param $para 请求的数据  
108 - * @param $input_charset 编码格式。默认值:空值  
109 - * return 远程输出的数据  
110 - */  
111 -function getHttpResponsePOST($url, $cacert_url, $para, $input_charset = '')  
112 -{  
113 -  
114 - if (trim($input_charset) != '') {  
115 - $url = $url . "_input_charset=" . $input_charset;  
116 - }  
117 - $curl = curl_init($url);  
118 - curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true); //SSL证书认证  
119 - curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); //严格认证  
120 - curl_setopt($curl, CURLOPT_CAINFO, $cacert_url); //证书地址  
121 - curl_setopt($curl, CURLOPT_HEADER, 0); // 过滤HTTP头  
122 - curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 显示输出结果  
123 - curl_setopt($curl, CURLOPT_POST, true); // post传输数据  
124 - curl_setopt($curl, CURLOPT_POSTFIELDS, $para); // post传输数据  
125 - $responseText = curl_exec($curl);  
126 - //var_dump( curl_error($curl) );//如果执行curl过程中出现异常,可打开此开关,以便查看异常内容  
127 - curl_close($curl);  
128 -  
129 - return $responseText;  
130 -}  
131 -  
132 -/**  
133 - * 远程获取数据,GET模式  
134 - * 注意:  
135 - * 1.使用Crul需要修改服务器中php.ini文件的设置,找到php_curl.dll去掉前面的";"就行了  
136 - * 2.文件夹中cacert.pem是SSL证书请保证其路径有效,目前默认路径是:getcwd().'\\cacert.pem'  
137 - * @param $url 指定URL完整路径地址  
138 - * @param $cacert_url 指定当前工作目录绝对路径  
139 - * return 远程输出的数据  
140 - */  
141 -function getHttpResponseGET($url, $cacert_url)  
142 -{  
143 - $curl = curl_init($url);  
144 - curl_setopt($curl, CURLOPT_HEADER, 0); // 过滤HTTP头  
145 - curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 显示输出结果  
146 - curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true); //SSL证书认证  
147 - curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); //严格认证  
148 - curl_setopt($curl, CURLOPT_CAINFO, $cacert_url); //证书地址  
149 - $responseText = curl_exec($curl);  
150 - //var_dump( curl_error($curl) );//如果执行curl过程中出现异常,可打开此开关,以便查看异常内容  
151 - curl_close($curl);  
152 -  
153 - return $responseText;  
154 -}  
155 -  
156 -/**  
157 - * 实现多种字符编码方式  
158 - * @param $input 需要编码的字符串  
159 - * @param $_output_charset 输出的编码格式  
160 - * @param $_input_charset 输入的编码格式  
161 - * return 编码后的字符串  
162 - */  
163 -function charsetEncode($input, $_output_charset, $_input_charset)  
164 -{  
165 - $output = "";  
166 - if (!isset($_output_charset))  
167 - $_output_charset = $_input_charset;  
168 - if ($_input_charset == $_output_charset || $input == null) {  
169 - $output = $input;  
170 - } elseif (function_exists("mb_convert_encoding")) {  
171 - $output = mb_convert_encoding($input, $_output_charset, $_input_charset);  
172 - } elseif (function_exists("iconv")) {  
173 - $output = iconv($_input_charset, $_output_charset, $input);  
174 - } else  
175 - die("sorry, you have no libs support for charset change.");  
176 - return $output;  
177 -}  
178 -  
179 -/**  
180 - * 实现多种字符解码方式  
181 - * @param $input 需要解码的字符串  
182 - * @param $_output_charset 输出的解码格式  
183 - * @param $_input_charset 输入的解码格式  
184 - * return 解码后的字符串  
185 - */  
186 -function charsetDecode($input, $_input_charset, $_output_charset)  
187 -{  
188 - $output = "";  
189 - if (!isset($_input_charset))  
190 - $_input_charset = $_input_charset;  
191 - if ($_input_charset == $_output_charset || $input == null) {  
192 - $output = $input;  
193 - } elseif (function_exists("mb_convert_encoding")) {  
194 - $output = mb_convert_encoding($input, $_output_charset, $_input_charset);  
195 - } elseif (function_exists("iconv")) {  
196 - $output = iconv($_input_charset, $_output_charset, $input);  
197 - } else  
198 - die("sorry, you have no libs support for charset changes.");  
199 - return $output;  
200 -}  
201 -  
202 -?>  
1 -<?php  
2 -  
3 -/* *  
4 - * MD5  
5 - * 详细:MD5加密  
6 - * 版本:3.3  
7 - * 日期:2012-07-19  
8 - * 说明:  
9 - * 以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。  
10 - * 该代码仅供学习和研究支付宝接口使用,只是提供一个参考。  
11 - */  
12 -  
13 -/**  
14 - * 签名字符串  
15 - * @param $prestr 需要签名的字符串  
16 - * @param $key 私钥  
17 - * return 签名结果  
18 - */  
19 -function md5Sign($prestr, $key)  
20 -{  
21 - $prestr = $prestr . $key;  
22 - return md5($prestr);  
23 -}  
24 -  
25 -/**  
26 - * 验证签名  
27 - * @param $prestr 需要签名的字符串  
28 - * @param $sign 签名结果  
29 - * @param $key 私钥  
30 - * return 签名结果  
31 - */  
32 -function md5Verify($prestr, $sign, $key)  
33 -{  
34 - $prestr = $prestr . $key;  
35 - $mysgin = md5($prestr);  
36 - if ($mysgin == $sign) {  
37 - return true;  
38 - } else {  
39 - return false;  
40 - }  
41 -}  
42 -  
43 -?>  
1 -<?php  
2 -  
3 -/* *  
4 - * 类名:AlipayNotify  
5 - * 功能:支付宝通知处理类  
6 - * 详细:处理支付宝各接口通知返回  
7 - * 版本:3.2  
8 - * 日期:2011-03-25  
9 - * 说明:  
10 - * 以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。  
11 - * 该代码仅供学习和研究支付宝接口使用,只是提供一个参考  
12 -  
13 - * ************************注意*************************  
14 - * 调试通知返回时,可查看或改写log日志的写入TXT里的数据,来检查通知返回是否正常  
15 - */  
16 -  
17 -require_once("alipay_core.function.php");  
18 -require_once("alipay_rsa.function.php");  
19 -  
20 -class AlipayNotify  
21 -{  
22 -  
23 - /**  
24 - * HTTPS形式消息验证地址  
25 - */  
26 - var $https_verify_url = 'https://mapi.alipay.com/gateway.do?service=notify_verify&';  
27 -  
28 - /**  
29 - * HTTP形式消息验证地址  
30 - */  
31 - var $http_verify_url = 'http://notify.alipay.com/trade/notify_query.do?';  
32 - var $alipay_config;  
33 -  
34 - function __construct($alipay_config)  
35 - {  
36 - $this->alipay_config = $alipay_config;  
37 - }  
38 -  
39 - function AlipayNotify($alipay_config)  
40 - {  
41 - $this->__construct($alipay_config);  
42 - }  
43 -  
44 - /**  
45 - * 针对notify_url验证消息是否是支付宝发出的合法消息  
46 - * @return 验证结果  
47 - */  
48 - function verifyNotify()  
49 - {  
50 - if (empty($_POST)) {//判断POST来的数组是否为空  
51 - return false;  
52 - } else {  
53 - //生成签名结果  
54 - $isSign = $this->getSignVeryfy($_POST, $_POST["sign"]);  
55 - //获取支付宝远程服务器ATN结果(验证是否是支付宝发来的消息)  
56 - $responseTxt = 'false';  
57 - if (!empty($_POST["notify_id"])) {  
58 - $responseTxt = $this->getResponse($_POST["notify_id"]);  
59 - }  
60 -  
61 - //写日志记录  
62 - //if ($isSign) {  
63 - // $isSignStr = 'true';  
64 - //}  
65 - //else {  
66 - // $isSignStr = 'false';  
67 - //}  
68 - //$log_text = "responseTxt=".$responseTxt."\n notify_url_log:isSign=".$isSignStr.",";  
69 - //$log_text = $log_text.createLinkString($_POST);  
70 - //logResult($log_text);  
71 - //验证  
72 - //$responsetTxt的结果不是true,与服务器设置问题、合作身份者ID、notify_id一分钟失效有关  
73 - //isSign的结果不是true,与安全校验码、请求时的参数格式(如:带自定义参数等)、编码格式有关  
74 - if (preg_match("/true$/i", $responseTxt) && $isSign) {  
75 - return true;  
76 - } else {  
77 - return false;  
78 - }  
79 - }  
80 - }  
81 -  
82 - /**  
83 - * 针对return_url验证消息是否是支付宝发出的合法消息  
84 - * @return 验证结果  
85 - */  
86 - function verifyReturn()  
87 - {  
88 - if (empty($_GET)) {//判断POST来的数组是否为空  
89 - return false;  
90 - } else {  
91 - //生成签名结果  
92 - $isSign = $this->getSignVeryfy($_GET, $_GET["sign"]);  
93 - //获取支付宝远程服务器ATN结果(验证是否是支付宝发来的消息)  
94 - $responseTxt = 'false';  
95 - if (!empty($_GET["notify_id"])) {  
96 - $responseTxt = $this->getResponse($_GET["notify_id"]);  
97 - }  
98 -  
99 - //写日志记录  
100 - //if ($isSign) {  
101 - // $isSignStr = 'true';  
102 - //}  
103 - //else {  
104 - // $isSignStr = 'false';  
105 - //}  
106 - //$log_text = "responseTxt=".$responseTxt."\n return_url_log:isSign=".$isSignStr.",";  
107 - //$log_text = $log_text.createLinkString($_GET);  
108 - //logResult($log_text);  
109 - //验证  
110 - //$responsetTxt的结果不是true,与服务器设置问题、合作身份者ID、notify_id一分钟失效有关  
111 - //isSign的结果不是true,与安全校验码、请求时的参数格式(如:带自定义参数等)、编码格式有关  
112 - if (preg_match("/true$/i", $responseTxt) && $isSign) {  
113 - return true;  
114 - } else {  
115 - return false;  
116 - }  
117 - }  
118 - }  
119 -  
120 - /**  
121 - * 获取返回时的签名验证结果  
122 - * @param $para_temp 通知返回来的参数数组  
123 - * @param $sign 返回的签名结果  
124 - * @return 签名验证结果  
125 - */  
126 - function getSignVeryfy($para_temp, $sign)  
127 - {  
128 - //除去待签名参数数组中的空值和签名参数  
129 - $para_filter = paraFilter($para_temp);  
130 -  
131 - //对待签名参数数组排序  
132 - $para_sort = argSort($para_filter);  
133 -  
134 - //把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串  
135 - $prestr = createLinkstring($para_sort);  
136 -  
137 - $isSgin = false;  
138 - switch (strtoupper(trim($this->alipay_config['sign_type']))) {  
139 - case "RSA" :  
140 - $isSgin = rsaVerify($prestr, trim($this->alipay_config['ali_public_key_path']), $sign);  
141 - break;  
142 - default :  
143 - $isSgin = false;  
144 - }  
145 -  
146 - return $isSgin;  
147 - }  
148 -  
149 - /**  
150 - * 获取远程服务器ATN结果,验证返回URL  
151 - * @param $notify_id 通知校验ID  
152 - * @return 服务器ATN结果  
153 - * 验证结果集:  
154 - * invalid命令参数不对 出现这个错误,请检测返回处理中partner和key是否为空  
155 - * true 返回正确信息  
156 - * false 请检查防火墙或者是服务器阻止端口问题以及验证时间是否超过一分钟  
157 - */  
158 - function getResponse($notify_id)  
159 - {  
160 - $transport = strtolower(trim($this->alipay_config['transport']));  
161 - $partner = trim($this->alipay_config['partner']);  
162 - $veryfy_url = '';  
163 - if ($transport == 'https') {  
164 - $veryfy_url = $this->https_verify_url;  
165 - } else {  
166 - $veryfy_url = $this->http_verify_url;  
167 - }  
168 - $veryfy_url = $veryfy_url . "partner=" . $partner . "&notify_id=" . $notify_id;  
169 - $responseTxt = getHttpResponseGET($veryfy_url, $this->alipay_config['cacert']);  
170 -  
171 - return $responseTxt;  
172 - }  
173 -  
174 -}  
175 -  
176 -?>  
1 -<?php  
2 -  
3 -/* *  
4 - * 支付宝接口RSA函数  
5 - * 详细:RSA签名、验签、解密  
6 - * 版本:3.3  
7 - * 日期:2012-07-23  
8 - * 说明:  
9 - * 以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。  
10 - * 该代码仅供学习和研究支付宝接口使用,只是提供一个参考。  
11 - */  
12 -  
13 -/**  
14 - * RSA签名  
15 - * @param $data 待签名数据  
16 - * @param $private_key_path 商户私钥文件路径  
17 - * return 签名结果  
18 - */  
19 -function rsaSign($data, $private_key_path)  
20 -{  
21 - $priKey = file_get_contents($private_key_path);  
22 - $res = openssl_get_privatekey($priKey);  
23 - openssl_sign($data, $sign, $res);  
24 - openssl_free_key($res);  
25 - //base64编码  
26 - $sign = base64_encode($sign);  
27 - return $sign;  
28 -}  
29 -  
30 -/**  
31 - * RSA验签  
32 - * @param $data 待签名数据  
33 - * @param $ali_public_key_path 支付宝的公钥文件路径  
34 - * @param $sign 要校对的的签名结果  
35 - * return 验证结果  
36 - */  
37 -function rsaVerify($data, $ali_public_key_path, $sign)  
38 -{  
39 - $pubKey = file_get_contents($ali_public_key_path);  
40 - $res = openssl_get_publickey($pubKey);  
41 - $result = (bool) openssl_verify($data, base64_decode($sign), $res);  
42 - openssl_free_key($res);  
43 - return $result;  
44 -}  
45 -  
46 -/**  
47 - * RSA解密  
48 - * @param $content 需要解密的内容,密文  
49 - * @param $private_key_path 商户私钥文件路径  
50 - * return 解密后内容,明文  
51 - */  
52 -function rsaDecrypt($content, $private_key_path)  
53 -{  
54 - $priKey = file_get_contents($private_key_path);  
55 - $res = openssl_get_privatekey($priKey);  
56 - //用base64将内容还原成二进制  
57 - $content = base64_decode($content);  
58 - //把需要解密的内容,按128位拆开解密  
59 - $result = '';  
60 - for ($i = 0; $i < strlen($content) / 128; $i++) {  
61 - $data = substr($content, $i * 128, 128);  
62 - openssl_private_decrypt($data, $decrypt, $res);  
63 - $result .= $decrypt;  
64 - }  
65 - openssl_free_key($res);  
66 - return $result;  
67 -}  
68 -  
69 -?>  
1 -<?php  
2 -  
3 -/* *  
4 - * 类名:AlipaySubmit  
5 - * 功能:支付宝各接口请求提交类  
6 - * 详细:构造支付宝各接口表单HTML文本,获取远程HTTP数据  
7 - * 版本:3.3  
8 - * 日期:2012-07-23  
9 - * 说明:  
10 - * 以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。  
11 - * 该代码仅供学习和研究支付宝接口使用,只是提供一个参考。  
12 - */  
13 -require_once("alipay_core.function.php");  
14 -require_once("alipay_rsa.function.php");  
15 -require_once("alipay_md5.function.php");  
16 -  
17 -class AlipaySubmit  
18 -{  
19 -  
20 - var $alipay_config;  
21 -  
22 - /**  
23 - * 支付宝网关地址(新)  
24 - */  
25 - var $alipay_gateway_new = 'https://mapi.alipay.com/gateway.do?';  
26 -  
27 - function __construct($alipay_config)  
28 - {  
29 - $this->alipay_config = $alipay_config;  
30 - }  
31 -  
32 - function AlipaySubmit($alipay_config)  
33 - {  
34 - $this->__construct($alipay_config);  
35 - }  
36 -  
37 - /**  
38 - * 生成签名结果  
39 - * @param $para_sort 已排序要签名的数组  
40 - * return 签名结果字符串  
41 - */  
42 - function buildRequestMysign($para_sort)  
43 - {  
44 - //把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串  
45 - $prestr = createLinkstring($para_sort);  
46 -  
47 - $mysign = "";  
48 - switch (strtoupper(trim($this->alipay_config['sign_type']))) {  
49 - case "RSA" :  
50 - $mysign = rsaSign($prestr, $this->alipay_config['private_key_path']);  
51 - break;  
52 - case "MD5" :  
53 - $mysign = md5Sign($prestr, $this->alipay_config['key']);  
54 - break;  
55 - default :  
56 - $mysign = "";  
57 - }  
58 -  
59 - return $mysign;  
60 - }  
61 -  
62 - /**  
63 - * 生成要请求给支付宝的参数数组  
64 - * @param $para_temp 请求前的参数数组  
65 - * @return 要请求的参数数组  
66 - */  
67 - function buildRequestPara($para_temp)  
68 - {  
69 - //除去待签名参数数组中的空值和签名参数  
70 - $para_filter = paraFilter($para_temp);  
71 -  
72 - //对待签名参数数组排序  
73 - $para_sort = argSort($para_filter);  
74 -  
75 - //生成签名结果  
76 - $mysign = $this->buildRequestMysign($para_sort);  
77 -  
78 - //签名结果与签名方式加入请求提交参数组中  
79 - $para_sort['sign'] = $mysign;  
80 - $para_sort['sign_type'] = strtoupper(trim($this->alipay_config['sign_type']));  
81 -  
82 - return $para_sort;  
83 - }  
84 -  
85 - /**  
86 - * 生成要请求给支付宝的参数数组  
87 - * @param $para_temp 请求前的参数数组  
88 - * @return 要请求的参数数组字符串  
89 - */  
90 - function buildRequestParaToString($para_temp)  
91 - {  
92 - //待请求参数数组  
93 - $para = $this->buildRequestPara($para_temp);  
94 -  
95 - //把参数组中所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串,并对字符串做urlencode编码  
96 - $request_data = createLinkstringUrlencode($para);  
97 -  
98 - return $request_data;  
99 - }  
100 -  
101 - /**  
102 - * 建立请求,以表单HTML形式构造(默认)  
103 - * @param $para_temp 请求参数数组  
104 - * @param $method 提交方式。两个值可选:post、get  
105 - * @param $button_name 确认按钮显示文字  
106 - * @return 提交表单HTML文本  
107 - */  
108 - function buildRequestForm($para_temp, $method, $button_name)  
109 - {  
110 - //待请求参数数组  
111 - $para = $this->buildRequestPara($para_temp);  
112 -  
113 - $sHtml = "<form id='alipaysubmit' name='alipaysubmit' action='" . $this->alipay_gateway_new . "_input_charset=" . trim(strtolower($this->alipay_config['input_charset'])) . "' method='" . $method . "'>";  
114 - while (list ($key, $val) = each($para)) {  
115 - $sHtml.= "<input type='hidden' name='" . $key . "' value='" . $val . "'/>";  
116 - }  
117 -  
118 - //submit按钮控件请不要含有name属性  
119 - $sHtml = $sHtml . "<input type='submit' value='" . $button_name . "'></form>";  
120 -  
121 - $sHtml = $sHtml . "<script>document.forms['alipaysubmit'].submit();</script>";  
122 -  
123 - return $sHtml;  
124 - }  
125 -  
126 - /**  
127 - * 建立请求,以模拟远程HTTP的POST请求方式构造并获取支付宝的处理结果  
128 - * @param $para_temp 请求参数数组  
129 - * @return 支付宝处理结果  
130 - */  
131 - function buildRequestHttp($para_temp)  
132 - {  
133 - $sResult = '';  
134 -  
135 - //待请求参数数组字符串  
136 - $request_data = $this->buildRequestPara($para_temp);  
137 -  
138 - //远程获取数据  
139 - $sResult = getHttpResponsePOST($this->alipay_gateway_new, $this->alipay_config['cacert'], $request_data, trim(strtolower($this->alipay_config['input_charset'])));  
140 -  
141 - return $sResult;  
142 - }  
143 -  
144 - /**  
145 - * 建立请求,以模拟远程HTTP的POST请求方式构造并获取支付宝的处理结果,带文件上传功能  
146 - * @param $para_temp 请求参数数组  
147 - * @param $file_para_name 文件类型的参数名  
148 - * @param $file_name 文件完整绝对路径  
149 - * @return 支付宝返回处理结果  
150 - */  
151 - function buildRequestHttpInFile($para_temp, $file_para_name, $file_name)  
152 - {  
153 -  
154 - //待请求参数数组  
155 - $para = $this->buildRequestPara($para_temp);  
156 - $para[$file_para_name] = "@" . $file_name;  
157 -  
158 - //远程获取数据  
159 - $sResult = getHttpResponsePOST($this->alipay_gateway_new, $this->alipay_config['cacert'], $para, trim(strtolower($this->alipay_config['input_charset'])));  
160 -  
161 - return $sResult;  
162 - }  
163 -  
164 - /**  
165 - * 用于防钓鱼,调用接口query_timestamp来获取时间戳的处理函数  
166 - * 注意:该功能PHP5环境及以上支持,因此必须服务器、本地电脑中装有支持DOMDocument、SSL的PHP配置环境。建议本地调试时使用PHP开发软件  
167 - * return 时间戳字符串  
168 - */  
169 - function query_timestamp()  
170 - {  
171 - $url = $this->alipay_gateway_new . "service=query_timestamp&partner=" . trim(strtolower($this->alipay_config['partner'])) . "&_input_charset=" . trim(strtolower($this->alipay_config['input_charset']));  
172 - $encrypt_key = "";  
173 -  
174 - $doc = new DOMDocument();  
175 - $doc->load($url);  
176 - $itemEncrypt_key = $doc->getElementsByTagName("encrypt_key");  
177 - $encrypt_key = $itemEncrypt_key->item(0)->nodeValue;  
178 -  
179 - return $encrypt_key;  
180 - }  
181 -  
182 -}  
183 -  
184 -?>  
@@ -93,14 +93,9 @@ class PayController extends AbstractAction @@ -93,14 +93,9 @@ class PayController extends AbstractAction
93 */ 93 */
94 public function aliwapreturnAction() 94 public function aliwapreturnAction()
95 { 95 {
96 - $this->setTitle('支付中心');  
97 - $this->setNavHeader('支付中心', Helpers::url('/home/orders'), false);  
98 - $data = array(  
99 - 'payBackPage' => true,  
100 - 'pageFooter' => true  
101 - );  
102 - // 渲染模板  
103 - $this->_view->display('index', $data); 96 + $aliwapService = new AliwapService();
  97 + $payRequestPars = $aliwapService->parseResponse($_GET);
  98 + $this->commonShowResult($payRequestPars, 18);
104 } 99 }
105 100
106 /** 101 /**
@@ -201,6 +196,31 @@ class PayController extends AbstractAction @@ -201,6 +196,31 @@ class PayController extends AbstractAction
201 196
202 $this->echoJson($data); 197 $this->echoJson($data);
203 } 198 }
204 -  
205 - 199 +
  200 + /**
  201 + * 通用显示结果的方法
  202 + * @param type $payResult
  203 + * @param type $payment
  204 + */
  205 + private function commonShowResult($payResult, $payment)
  206 + {
  207 + $this->setTitle('支付中心');
  208 + $this->setNavHeader('支付中心', Helpers::url('/home/orders'), false);
  209 +
  210 + $view = 'notneedpay';
  211 + if ($payResult->payResult == 200) {
  212 + $view = 'index';
  213 + if (!empty($payResult->orderCode)) {
  214 + //支付成功,发送一次支付确认
  215 + $uid = $this->getUid();
  216 + OrderData::payConfirm($payResult->orderCode, $payment, $uid);
  217 + }
  218 + }
  219 +
  220 + $data = array(
  221 + 'payBackPage' => true,
  222 + 'pageFooter' => true
  223 + );
  224 + $this->_view->display($view, $data);
  225 + }
206 } 226 }