支付宝即时到帐接口在商户服务器与支付宝服务器进行数据交互的时候需要进行数据前面,主要目的是为了防止数据在传输过程中被恶意窜改。
所谓签名即根据即时到帐交易接口文档中的请求参数列表中,除去 sign、sign_type 两个参数外,其他需要使用到的参数按照从 a 到 z 的顺序排序(若遇到相同首字母,则看第二个字母,
以此类推),然后将拼接成的字符串与支付宝密钥拼接,再进行MD5运算(以md5类型的签名举例说明)。得到的32位字符就是签名结果字符串。
在即时到帐交易中一共需要进行两次签名:
第一次是支付前构造支付数据,需要将支付参数和签名结果字符串用POST方式提交到支付宝网关(https://mapi.alipay.com/gateway.do)
第二次是支付成功后支付宝服务器通过return_url和notify_url进行同步通知和异步通知时会向商户服务器分别用get方式和post方式发送支付结果处理数据,商户服务器需要根据接受到的数据和签名信息判断该消息是否为支付宝服务器发送的,并根据结果和状态对商户本地程序操作相关的业务逻辑
不幸的是在项目中两次需要验证签名的地方都出了问题,下面讲一下我遇到的状况和解决方法
支付前构造支付数据的签名错误
我是直接使用支付宝官方提供的demo进行开发的,首先在本地跑了一下没有问题,放在服务器环境后进行支付直接跳转到支付宝的错误页面。
错误代码:ILLEGAL_SIGN 错误信息:调试错误,请回到请求来源地,重新发起请求
支付宝商家帮助中心也简明扼要的给出了解决和排查办法:https://cshall.alipay.com/support/help_detail.htm?help_id=397063
我这里是使用utf-8格式的php编写程序,经过排查是在POST提交这一步中文的商品名乱码导致的签名错误
解决方式一:
打开alipay_submit.class.php,找到以下代码(99行左右)
- $sHtml = "<form id='alipaysubmit' name='alipaysubmit' action='".$this->alipay_gateway_new."_input_charset=".trim(strtolower($this->alipay_config['input_charset']))."' method='".$method."'>";
替换为
- $sHtml = "<meta http-equiv='content-type' content='text/html; charset=utf-8'><form id='alipaysubmit' name='alipaysubmit' action='".$gateway."_input_charset=".trim(strtolower($aliapy_config['input_charset']))."' method='".$method."'>";
解决方式二:
在相应的PHP页面声明编码类型为utf-8即可
- header("content-type: text/html;charset=utf-8");
支付成功后消息通知中的签名不一致
对于消息通知签名不正确支付宝商户帮助中心也给出了解决和排查办法:https://cshall.alipay.com/support/help_detail.htm?help_id=397351
经过查找资料,网友们给出了几种常见的错误类型:
第一种情况:由于编码导致中文传回是乱码的情况导致sign和mysign不等。可参考这篇文章的案例
http://www.imlqw.com/322.html(目前连接已经失效)
第二种情况:由于post和get提交的问题导致sign和mysign不等,可参考以下文章:
http://my.oschina.net/u/214582/blog/52140
第三种情况:由于官方提供的paraFilter方法bug问题导致sign和mysign不等,可参考一下文章:
http://club.alipay.com/read-htm-tid-10244623-page-e.html
第四种情况:由于参数问题导致的sign和mysign不等的情况。