支付宝集成时,有同步返回地址return_url和异步通知地址notify_url,这两个地址中的参数与签名验证有非常大的关系,在支付宝的说明中,强调return_url不可以有自定义参数,否则会导致sign和mysign不相等,但有时我们需要一些自定义参数来做判断,怎么办呢?
目录
签名验证机制
支付宝签名有两次,第一次是发送的时候,第二次是返回的时候,返回又分为同步返回和异步通知,这两个的签名方式是相同的。
向支付宝发送参数时,调用如下函数产生签名,并构建生成表单的数组
function buildRequestPara($para_temp,$aliapy_config) { //除去待签名参数数组中的空值和签名参数 $para_filter = paraFilter($para_temp); //对待签名参数数组排序 $para_sort = argSort($para_filter); //生成签名结果 $mysign = buildMysign($para_sort, trim($aliapy_config['key']), strtoupper(trim($aliapy_config['sign_type']))); //签名结果与签名方式加入请求提交参数组中 $para_sort['sign'] = $mysign; $para_sort['sign_type'] = strtoupper(trim($aliapy_config['sign_type'])); return $para_sort; }
数据返回时,调用下面的函数生成签名
function verifyReturn(){ if(empty($_GET)) {//判断POST来的数组是否为空 return false; } else { //生成签名结果 $mysign = $this->getMysign($_GET); //获取支付宝远程服务器ATN结果(验证是否是支付宝发来的消息) $responseTxt = 'true'; if (! empty($_GET["notify_id"])) {$responseTxt = $this->getResponse($_GET["notify_id"]);} //写日志记录 $log_text = "responseTxt=".$responseTxt."\n notify_url_log:sign=".$_GET["sign"]."&mysign=".$mysign.","; $log_text = $log_text.createLinkString($_GET); logResult($log_text); //验证 //$responsetTxt的结果不是true,与服务器设置问题、合作身份者ID、notify_id一分钟失效有关 //mysign与sign不等,与安全校验码、请求时的参数格式(如:带自定义参数等)、编码格式有关 if (preg_match("/true$/i",$responseTxt) && $mysign == $_GET["sign"]) { return true; } else { return false; } } } function getMysign($para_temp) { //除去待签名参数数组中的空值和签名参数 $para_filter = paraFilter($para_temp); //对待签名参数数组排序 $para_sort = argSort($para_filter); //生成签名结果 $mysign = buildMysign($para_sort, trim($this->aliapy_config['key']), strtoupper(trim($this->aliapy_config['sign_type']))); return $mysign; }
两者最终都要调用buileMysign函数,如下
function buildMysign($sort_para,$key,$sign_type = "MD5") { //把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串 $prestr = createLinkstring($sort_para); //把拼接后的字符串再与安全校验码直接连接起来 $prestr = $prestr.$key; //把最终的字符串签名,获得签名结果 $mysgin = sign($prestr,$sign_type); return $mysgin;
从这些过程可以得出以下结论
- 支付宝的签名是根据程序构建的参数进行的,发送时参数由本地程序构建,所以受自己控制,只要参数正确,基本可以成功,去除空参数等操作是支付宝的库函数来完成的。
- 接收回传的参数时,对于同步返回的参数,$_GET数组的内容非常重要,因为验证回传参数时(调用verfyReturn()函数),首先将$_GET的内容全部传给getMysign()方法,支付宝会get给我们一个sign,只有根据回传参数产生出相同的sign,才可以验证通过。这就是我们不能使用自定义参数的原因,如果增加了自定义参数,getMysign()就会带有杂质,跟支付宝生成的sign过程不同了,自然结果就要不对。
如何让自定义参数跟支付宝兼容
这个自定义参数问题只存在于return_url中,因为同步回传使用GET方式,异步通知使用POST方式,POST不受url中的自定义参数影响。
假设你的自定义参数是custom_val
在调用支付宝的验证参数前,将这个自定义参数从$_GET数组中去掉,支付宝验证结束后再恢复就可以了。
$get_temp = $_GET; unset($_GET['custom_val']); //调用支付宝验证签名接口 $alipayNotify = new AlipayNotify($aliapy_config); $verify_result = $alipayNotify->verifyNotify(); //恢复$_GET数组 $_GET = $get_temp; unset($get_temp);
为什么notify_url地址不能带有自定义参数
在指定notify_url时,合法的方式如
https://www.solagirl.net/notify_url.php
不合法的方式如
https://www.solagirl.net/notify_url.php?order_id=10
与其说第二种格式不合法,不如说它是无效的。为什么这样说?因为不论你在这个地址后面带上多少自定义的参数,支付宝通过异步方式向你POST数据时,都会把?后面的参数去掉,所以带了也是白带,起不了任何作用,更不可能影响签名判断。这点似乎不如paypal方便,要区分执行过程只能靠POST过来的数据。
因此支付宝的notify_url不是不可以带有自定义参数,而是带了也没用,自作多情而已。
$get_temp = $_GET;
unset($_GET[‘custom_val’]);
//调用支付宝验证签名接口
$alipayNotify = new AlipayNotify($aliapy_config);
$verify_result = $alipayNotify->verifyNotify();
//恢复$_GET数组
$_GET = $get_temp;
unset($get_temp);
请问这个是加在哪里的呢?
如果你用了支付宝提供的class,就加在支付宝验证返回的参数之前,因为支付宝的class直接使用了$_GET数组,没验证参数的合法性。
非常感谢回复,你这段代码里面,$get_temp = $_GET;
unset($_GET[‘custom_val’]);
//调用支付宝验证签名接口
$alipayNotify = new AlipayNotify($aliapy_config);
$verify_result = $alipayNotify->verifyNotify(); “create_direct_pay_by_user”,
“partner” => trim($alipay_config[‘partner’]),
“payment_type” => $payment_type,
“notify_url” => $notify_url,
“return_url” => $return_url,
“seller_email” => $seller_email,
“out_trade_no” => $out_trade_no,
“subject” => $subject,
“total_fee” => $total_fee,
“body” => $body,
“show_url” => $show_url,
“anti_phishing_key” => $anti_phishing_key,
“exter_invoke_ip” => $exter_invoke_ip,
“_input_charset” => trim(strtolower($alipay_config[‘input_charset’])),
“extra_common_param”=> $month,
“userid” => $userid, $service_id<–这个是自定义参数
我把你给出的那几行代码加载return_url里面,并且打印验证前的$_GET和验证后$_GET,都没有发现自定义参数的存在,这是为何呢?是否因为支付宝接口版本更新导致现在的过滤方式有所改变呢?
$_GET获取的是url里的参数,举个最简单的例子,如果WordPress使用了默认固定链接,return_url就可能是yourdomain.com/?p=10&…,这个p就是自定义参数。
同步返回的自定义参数是由return_url结构决定的,支付宝是不会传递它不支持的参数的。
已经处理好了,可以在notify_url和return_url后面增加自定义参数,在返回时用你的代码过滤或者支付宝自己的过滤代码过滤就可以了。
回调接口怎么链接的,求楼主教一下。
关于钱的东西都非常的复杂哟!
博主这都知道 真是厉害啊
哇,可爱多,我爱吃
你家狗狗病好了没!
还行,今天挺有精神,也想吃东西了。就是给狗看个病真是贵,这几天花出去两千多了,还没完呢