[PHP]误读支付宝接口可能引发的乌龙

------------------------------------------------------------------------------------

之所以发现这个坑,源起项目中的支付宝页面跳转同步通知页return_url中的$verify_result始终返回false。

$alipayNotify = new Alipaynotify($alipay_config); //支付宝通知处理类

$verify_result = $alipayNotify->verifyReturn();

verifyReturn函数用于针对return_url验证消息是否是支付宝发出的合法消息

其中生成签名结果一项,$isSign = $this->getSignVeryfy($_GET, $_GET['sign']);返回true或false

getSignVeryfy是获取返回时的签名验证结果,该函数做以下三件事(调用的均为支付宝公用函数):

1. 除去待签名参数数组中的空值和签名参数,paraFilter

2. 对签名参数数组排序,argSort

3. 把数组所有元素,按照‘参数=参数值’的模式用“&”字符拼接成字符串,createLinkstring

4. 如果是MD5加密,使用md5Verify验证签名,返回true或false

第1,2两步都没有问题,到第3步时,我们所期待的结果是这样子的:

而打印后返回的结果是这样的:

显然,这里转换出了问题,下面来看一下createLinkstring函数的具体实现

/**
 * 把数组所有元素,按照"参数=参数值"的模式用“&”字符拼接成字符串
 * @param $para 需要拼接的数组
 * return 拼接完成以后的字符串
 */
function createLinkstring($para) {
    $arg = '';
    while (list ($key, $val) = each ($para)) {
        $arg .= $key ."=".$val ."&";
    }
    //去掉最后一个&字符
    $arg = substr($arg, 0, count($arg)-2);

    //如果存在转义字符,那么去掉释义
    if(get_magic_quotes_gpc()) {
        $arg = stripslashes($arg);
    }

    return $arg;
}

上面连接字符串部分使用foreach实现都不影响$arg, substr使用rtrim实现也不影响$arg, get_agic_quotes_gpc在5.4以上才废弃,但是里面不存在转义字符;再看上面打印的结果,很有可能是 “&” 符号出了问题,程序部分将 “&” 符改为 “&” 后终于得到了期望的结果。

$arg .= $key ."=".$val ."&";

大家猜想一下,如果把上面的双引号改为单引号后,能不能得到期望的结果,如下(回复中解答):

$arg .= $key .'='.$val .'&';

另外,出现这种情况不排除PHP版本问题,大家试过之后不妨留言告诉我 你们的情况。

  

异步通知url和同步通知url中都不能有自定义参数,由于提交支付宝时的参数加密与跳转商家页面的验证加密机制是一致的,所以一旦url中含有自定义参数,导致提交前与提交后不相等,$verify_result将返回false,即无法通过验证;不通过这一步验证,商户的数据操作始终无法进行,如果就此忽略$verify_result必然存在安全问题。

对于mvc形式的动态url,需要去除提交时不需要的参数,保证干净,如:

  unset($_GET['controller']);

  unset($_GET['method']);

  $alipayNotify = new Alipaynotify($alipay_config);

  $verify_result = $alipayNotify->verifyReturn();

  if($verify_result) {

    //验证成功(商户逻辑代码)

  } else {

    //验证失败(调试请看Alipaynotify.php页面的verifyReturn函数)

  }

  

  同步url的参数保证了干净,同样别忘了提交时不要带有,如:

  unset($_GET['controller']);

  unset($_GET['method']);

  $this->load->library('Alipaysubmit');

  $alipay_config = $this->alipay_config;

  $alipaySubmit = new Alipaysubmit($alipay_config);

  ...

  

  为什么异步notify_url会失效?

  如果异步notify_url地址是mvc形式,因为你的控制器和方法已经被支付宝过滤掉,那么支付宝将找不到页面,所以无法通知到这个指定的地址。

Link:http://www.cnblogs.com/farwish/p/4309520.html

@黑眼诗人 <www.farwish.com>

原文地址:https://www.cnblogs.com/farwish/p/4309520.html