V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
konakona
V2EX  ›  支付宝

支付宝-担保交易 SIGN 生成问题

  •  
  •   konakona · 2015-01-23 03:26:28 +08:00 · 3087 次点击
    这是一个创建于 3576 天前的主题,其中的信息可能已经有所发展或是发生改变。
    现在在整合担保交易到项目中。

    之前也多次开发过支付宝-担保交易的接口,因为支付宝各种接口相似度高,因此封装好后通用性就比较强,所以把以前的代码重写了下即可兼容担保交易的接口。

    也在localhost新建了一个文件夹,实测了官方PHP UTF-8 DEMO的运作,DEMO一切正常,能够到达支付宝页面并正确读取出商品信息和价格等。

    但是我的代码,死活签名验证不通过,打印数据如下:


    第一段是打印数组,打印的是“待签名”的数组,可以确定没有问题(我仔细的核对过API的PD“4 请求参数说明”),这部分用的也是官方APIDemo 中的 buildRequestPara()方法。在这里,进行了签名生成。

    签名一直过不了!

    我是已经想不明白了……大半夜的……在蹲墙角ing……可能我明天起来换一个心情又运行了呢!!!(画圈圈去)
    第 1 条附言  ·  2015-01-23 15:15:29 +08:00
    我是通过生成URL跳转过去进行支付。
    并非form点击确认按钮提交哦~
    13 条回复    2015-01-23 23:05:32 +08:00
    Sunyanzi
        1
    Sunyanzi  
       2015-01-23 04:58:50 +08:00   ❤️ 2
    输出的数组格式没问题 ... 所以原因只可能有三点 ...

    第一检查你的 api key 有没有写对 ... 就是附在待签名部分尾巴上的那个 ...

    第二你的待签名字符串根本没有打全让人怎么看 ...

    第三也是可能性最大的一点 ... &not 在 html 里面是 ¬ 这个符号 ...

    如果你是通过 HTML 跳转支付宝的时候记得转义 URL ... 细心比什么都重要 ...
    Sunyanzi
        2
    Sunyanzi  
       2015-01-23 05:02:19 +08:00
    咦我刚知道 V2 居然不转义 HTML 的吗 ... @Livid 这是个 feature 还是个 bug ..?

    我是说 &not 在 HTML 里面是 ¬ 这个符号 ... 这会干扰到 notify 传值 ...
    Livid
        3
    Livid  
    MOD
       2015-01-23 05:03:45 +08:00
    @Sunyanzi 谢谢反馈。我看一下。可能是 bug。
    Sunyanzi
        4
    Sunyanzi  
       2015-01-23 05:07:55 +08:00
    @Livid 好快!
    Livid
        5
    Livid  
    MOD
       2015-01-23 05:24:23 +08:00
    @Sunyanzi Fixed.
    xoxo
        6
    xoxo  
       2015-01-23 08:31:18 +08:00   ❤️ 1
    这个是不是因为楼主用了框架( $_GET['a'] $_GET['c'] )? 然后支付宝验签直接取的$_GET、$_POST
    baocaixiong
        7
    baocaixiong  
       2015-01-23 09:30:39 +08:00   ❤️ 1
    @xoxo
    如果框架对$_GET和$_POST修改过,需要重新赋值回来的。
    cevincheung
        8
    cevincheung  
       2015-01-23 09:37:21 +08:00   ❤️ 1
    @Sunyanzi 在HTML的显示不会影响到HTML值。

    @konakona 不使用http_build_query就好了。
    konakona
        9
    konakona  
    OP
       2015-01-23 15:12:47 +08:00
    @Sunyanzi
    @xoxo
    @cevincheung
    @baocaixiong
    这个是发送过去的SIGN验证不通过,不是callback或者notify的时候,我这边不通过。
    没有用http_build_query(),处理待签名数字和生成签名,都是用的官方DEMO里的函数。(本来我是自己写的,但是签名一直有问题,索性就将官方DEMO中的关键函数整个移植到了我的代码中,以肯定2者的处理方式一模一样)
    所有数组ksort了,去掉了空格,生成了a=b&b=c&c=d这样的格式。
    `
    /**
    * 生成要请求给支付宝的参数数组
    * @param $para_temp 请求前的参数数组
    * @return 要请求的参数数组字符串
    */
    private function buildRequestParaToString($para_temp)
    {
    //待请求参数数组
    $para = $this->buildRequestPara($para_temp);
    dump($para);

    //把参数组中所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串,并对字符串做urlencode编码
    $request_data = createLinkstringUrlencode($para);
    dump($request_data);

    return $request_data;
    }

    /**
    * 生成签名结果
    * @param $para_sort 已排序要签名的数组
    * return 签名结果字符串
    */
    private function buildRequestMysign($para_sort)
    {
    //把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
    $prestr = $this->createLinkstring($para_sort);
    $mysign = md5($prestr . $this->alipay_secret_key);
    return $mysign;
    }

    /**
    * 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
    * @param $para 需要拼接的数组
    * return 拼接完成以后的字符串
    */
    private 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;
    }

    `
    cevincheung
        10
    cevincheung  
       2015-01-23 15:19:01 +08:00
    @konakona

    function get_payment_url($trade_id,$price) {

    $url = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME']."?action=notify";

    $partner = 'xxxx';
    $secret = 'xxxxxxxxx';

    $p = array();

    $p['logistics_type'] = 'EXPRESS';
    $p['logistics_fee'] = '0';
    $p['logistics_payment'] = 'BUYER_PAY_AFTER_RECEIVE';

    $p['service'] = 'create_direct_pay_by_user';
    $p['partner'] = $partner;
    $p['_input_charset'] = 'utf-8';
    $p['notify_url'] = $url;
    $p['return_url'] = $url;
    $p['out_trade_no'] = $trade_id;
    $p['subject'] = "支付订单 {$trade_id}";
    $p['payment_type'] = 1;
    $p['seller_id'] = $partner;
    //$p['total_fee'] = $price;
    $p['price'] = $price;
    $p['quantity'] = 1;
    $p['body'] = "支付订单 {$trade_id}";
    ksort($p);

    $sign_str = null;foreach ($p as $k=>$v) $sign_str .= "{$k}={$v}&";$sign_str = substr($sign_str,0,-1);

    $p['sign'] = md5($sign_str.$secret);
    $p['sign_type'] = 'MD5';

    $query_string = http_build_query($p);

    return 'https://mapi.alipay.com/gateway.do?'.$query_string;

    }



    签名的值不能经过urlencode
    konakona
        11
    konakona  
    OP
       2015-01-23 15:20:27 +08:00
    @Sunyanzi
    =.= 果然..我刚刚恍然大悟...尼玛用HTML生成的含有&not被转义后的URL肯定访问不了..现在已经OK了!
    Sunyanzi
        12
    Sunyanzi  
       2015-01-23 16:28:12 +08:00
    @cevincheung 再多学学吧 ...

    @konakona 我总觉得最悲哀的事莫过于我告诉了你答案你自己还要琢磨很久才看明白 ...
    konakona
        13
    konakona  
    OP
       2015-01-23 23:05:32 +08:00
    @Sunyanzi 看大头传奇去了...
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3076 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 13:17 · PVG 21:17 · LAX 05:17 · JFK 08:17
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.