SnsSigCheck.php 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. <?php
  2. /**
  3. * 生成签名类
  4. *
  5. * @version 3.0.3
  6. * @author open.qq.com
  7. * @copyright © 2012, Tencent Corporation. All rights reserved.
  8. * @ History:
  9. * 3.0.3 | nemozhang | 2012-08-28 16:40:20 | support cpay callback sig verifictaion.
  10. * 3.0.2 | sparkeli | 2012-03-06 17:58:20 | add statistic fuction which can report API's access time and number to background server
  11. * 3.0.1 | nemozhang | 2012-02-14 17:58:20 | resolve a bug: at line 108, change 'post' to $method
  12. * 3.0.0 | nemozhang | 2011-12-12 11:11:11 | initialization
  13. */
  14. /**
  15. * 生成签名类
  16. */
  17. class SnsSigCheck
  18. {
  19. /**
  20. * 生成签名
  21. *
  22. * @param string $method 请求方法 "get" or "post"
  23. * @param string $url_path
  24. * @param array $params 表单参数
  25. * @param string $secret 密钥
  26. */
  27. public static function makeSig($method, $url_path, $params, $secret)
  28. {
  29. $mk = self::makeSource($method, $url_path, $params);
  30. $my_sign = hash_hmac("sha1", $mk, strtr($secret, '-_', '+/'), true);
  31. $my_sign = base64_encode($my_sign);
  32. return $my_sign;
  33. }
  34. private static function makeSource($method, $url_path, $params)
  35. {
  36. $strs = strtoupper($method) . '&' . rawurlencode($url_path) . '&';
  37. ksort($params);
  38. $query_string = array();
  39. foreach ($params as $key => $val) {
  40. array_push($query_string, $key . '=' . $val);
  41. }
  42. $query_string = join('&', $query_string);
  43. return $strs . str_replace('~', '%7E', rawurlencode($query_string));
  44. }
  45. /**
  46. * 验证回调发货URL的签名 (注意和普通的OpenAPI签名算法不一样,详见@refer的说明)
  47. *
  48. * @param string $method 请求方法 "get" or "post"
  49. * @param string $url_path
  50. * @param array $params 腾讯调用发货回调URL携带的请求参数
  51. * @param string $secret 密钥
  52. * @param string $sig 腾讯调用发货回调URL时传递的签名
  53. *
  54. * @refer
  55. * http://wiki.open.qq.com/wiki/%E5%9B%9E%E8%B0%83%E5%8F%91%E8%B4%A7URL%E7%9A%84%E5%8D%8F%E8%AE%AE%E8%AF%B4%E6%98%8E_V3
  56. */
  57. public static function verifySig($method, $url_path, $params, $secret, $sig, &$sig_new)
  58. {
  59. unset($params['sig']);
  60. if (isset($params['cee_extend'])) {
  61. unset($params['cee_extend']);
  62. }
  63. // 先使用专用的编码规则对value编码
  64. foreach ($params as $k => $v) {
  65. $params[$k] = self::encodeValue($v);
  66. }
  67. // 再计算签名
  68. $sig_new = self::makeSig($method, $url_path, $params, $secret);
  69. return $sig_new == $sig;
  70. }
  71. /**
  72. * 回调发货URL专用的编码算法
  73. * 编码规则为:除了 0~9 a~z A~Z !*()之外其他字符按其ASCII码的十六进制加%进行表示,例如"-"编码为"%2D"
  74. * @refer
  75. * http://wiki.open.qq.com/wiki/%E5%9B%9E%E8%B0%83%E5%8F%91%E8%B4%A7URL%E7%9A%84%E5%8D%8F%E8%AE%AE%E8%AF%B4%E6%98%8E_V3
  76. */
  77. private static function encodeValue($value)
  78. {
  79. $rst = '';
  80. $len = strlen($value);
  81. for ($i = 0; $i < $len; $i++) {
  82. $c = $value[$i];
  83. if (preg_match("/[a-zA-Z0-9!\(\)*]{1,1}/", $c)) {
  84. $rst .= $c;
  85. } else {
  86. $rst .= ("%" . sprintf("%02X", ord($c)));
  87. }
  88. }
  89. return $rst;
  90. }
  91. }
  92. // end of script