YZApiProtocol.php 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. <?php
  2. class YZApiProtocol {
  3. const APP_ID_KEY = 'app_id';
  4. const METHOD_KEY = 'method';
  5. const TIMESTAMP_KEY = 'timestamp';
  6. const FORMAT_KEY = 'format';
  7. const VERSION_KEY = 'v';
  8. const SIGN_KEY = 'sign';
  9. const SIGN_METHOD_KEY = 'sign_method';
  10. const TOKEN_KEY = 'access_token';
  11. const ALLOWED_DEVIATE_SECONDS = 600;
  12. const ERR_SYSTEM = -1;
  13. const ERR_INVALID_APP_ID = 40001;
  14. const ERR_INVALID_APP = 40002;
  15. const ERR_INVALID_TIMESTAMP = 40003;
  16. const ERR_EMPTY_SIGNATURE = 40004;
  17. const ERR_INVALID_SIGNATURE = 40005;
  18. const ERR_INVALID_METHOD_NAME = 40006;
  19. const ERR_INVALID_METHOD = 40007;
  20. const ERR_INVALID_TEAM = 40008;
  21. const ERR_PARAMETER = 41000;
  22. const ERR_LOGIC = 50000;
  23. public static function sign($appSecret, $params, $method = 'md5') {
  24. if (!is_array($params)) $params = array();
  25. ksort($params);
  26. $text = '';
  27. foreach ($params as $k => $v) {
  28. $text .= $k . $v;
  29. }
  30. return self::hash($method, $appSecret . $text . $appSecret);
  31. }
  32. private static function hash($method, $text) {
  33. switch ($method) {
  34. case 'md5':
  35. default:
  36. $signature = md5($text);
  37. break;
  38. }
  39. return $signature;
  40. }
  41. public static function allowedSignMethods() {
  42. return array('md5');
  43. }
  44. public static function allowedFormat() {
  45. return array('json');
  46. }
  47. public static function doc() {
  48. return array(
  49. 'params' => array(
  50. self::APP_ID_KEY => array(
  51. 'type' => 'String',
  52. 'required' => true,
  53. 'desc' => 'App ID',
  54. ),
  55. self::METHOD_KEY => array(
  56. 'type' => 'String',
  57. 'required' => true,
  58. 'desc' => 'API接口名称',
  59. ),
  60. self::TIMESTAMP_KEY => array(
  61. 'type' => 'String',
  62. 'required' => true,
  63. 'desc' => '时间戳,格式为yyyy-mm-dd HH:mm:ss,例如:2013-05-06 13:52:03。服务端允许客户端请求时间误差为' . intval(self::ALLOWED_DEVIATE_SECONDS / 60) . '分钟。',
  64. ),
  65. self::FORMAT_KEY => array(
  66. 'type' => 'String',
  67. 'required' => false,
  68. 'desc' => '可选,指定响应格式。默认json,目前支持格式为json',
  69. ),
  70. self::VERSION_KEY => array(
  71. 'type' => 'String',
  72. 'required' => true,
  73. 'desc' => 'API协议版本,可选值:1.0',
  74. ),
  75. self::SIGN_KEY => array(
  76. 'type' => 'String',
  77. 'required' => true,
  78. 'desc' => '对 API 输入参数进行 md5 加密获得,详细参考签名章节',
  79. ),
  80. self::SIGN_METHOD_KEY => array(
  81. 'type' => 'String',
  82. 'required' => false,
  83. 'desc' => '可选,参数的加密方法选择。默认为md5,可选值是:md5',
  84. ),
  85. self::TOKEN_KEY => array(
  86. 'type' => 'String',
  87. 'required' => true,
  88. 'desc' => '商户通过Oauth2.0授权给开发者的AccessToken',
  89. ),
  90. ),
  91. );
  92. }
  93. public static function errors() {
  94. return array(
  95. 'response' => array (
  96. 'code' => array (
  97. 'type' => 'Number',
  98. 'desc' => '错误编号',
  99. 'example' => 40002,
  100. 'required' => true,
  101. ),
  102. 'msg' => array (
  103. 'type' => 'String',
  104. 'desc' => '错误信息',
  105. 'example' => 'invalid app',
  106. 'required' => true,
  107. ),
  108. 'params' => array (
  109. 'type' => 'List',
  110. 'desc' => '请求参数列表',
  111. 'example' => array(
  112. 'app_id' => 'ac9aaepv37d2a5guc',
  113. 'method' => 'kdt.trades.sold.get',
  114. 'timestamp' => '2014-01-20 20:38:42',
  115. 'format' => 'json',
  116. 'sign_method' => 'md5',
  117. 'v' => '1.0',
  118. 'sign' => 'wi93n31d034a9207ert7d3971e3vno10',
  119. ),
  120. 'required' => true,
  121. ),
  122. ),
  123. 'errors' => array(
  124. self::ERR_SYSTEM => array(
  125. 'desc' => '系统错误',
  126. 'suggest' => '',
  127. ),
  128. self::ERR_INVALID_APP_ID => array(
  129. 'desc' => '未指定 AppId',
  130. 'suggest' => '请求时传入 AppId',
  131. ),
  132. self::ERR_INVALID_APP => array(
  133. 'desc' => '无效的App',
  134. 'suggest' => '申请有效的 AppId',
  135. ),
  136. self::ERR_INVALID_TIMESTAMP => array(
  137. 'desc' => '无效的时间参数',
  138. 'suggest' => '以当前时间重新发起请求;如果系统时间和服务器时间误差超过10分钟,请调整系统时间',
  139. ),
  140. self::ERR_EMPTY_SIGNATURE => array(
  141. 'desc' => '请求没有签名',
  142. 'suggest' => '请使用协议规范对请求中的参数进行签名',
  143. ),
  144. self::ERR_INVALID_SIGNATURE => array(
  145. 'desc' => '签名校验失败',
  146. 'suggest' => '检查 AppId 和 AppSecret 是否正确;如果是自行开发的协议分装,请检查代码',
  147. ),
  148. self::ERR_INVALID_METHOD_NAME => array(
  149. 'desc' => '未指定请求的 Api 方法',
  150. 'suggest' => '指定 Api 方法',
  151. ),
  152. self::ERR_INVALID_METHOD => array(
  153. 'desc' => '请求非法的方法',
  154. 'suggest' => '检查请求的方法的值',
  155. ),
  156. self::ERR_INVALID_TEAM => array(
  157. 'desc' => '校验团队信息失败',
  158. 'suggest' => '检查团队是否有效、是否绑定微信',
  159. ),
  160. self::ERR_PARAMETER => array(
  161. 'desc' => '请求方法的参数错误',
  162. 'suggest' => '',
  163. ),
  164. self::ERR_LOGIC => array(
  165. 'desc' => '请求方法时业务逻辑发生错误',
  166. 'suggest' => '',
  167. ),
  168. ),
  169. );
  170. }
  171. }