OpenApiV3.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. <?php
  2. /**
  3. * PHP SDK for OpenAPI V3
  4. *
  5. * @version 3.0.5
  6. * @author open.qq.com
  7. * @copyright © 2012, Tencent Corporation. All rights reserved.
  8. * @ History:
  9. * 3.0.6 | coolinchen| 2013-02-28 11:20:12| modify response code
  10. * 3.0.5 | coolinchen| 2012-10-08 11:20:12 | support printing request string and result
  11. * 3.0.4 | coolinchen| 2012-09-07 10:20:12 | support POST request in "multipart/form-data" format
  12. * 3.0.3 | nemozhang | 2012-08-28 16:40:20 | support cpay callback sig verifictaion
  13. * 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
  14. * 3.0.1 | nemozhang | 2012-02-14 17:58:20 | resolve a bug: at line 108, change 'post' to $method
  15. * 3.0.0 | nemozhang | 2011-12-12 11:11:11 | initialization
  16. */
  17. require_once dirname(__FILE__) . '/lib/SnsNetwork.php';
  18. require_once dirname(__FILE__) . '/lib/SnsSigCheck.php';
  19. require_once dirname(__FILE__) . '/lib/SnsStat.php';
  20. /**
  21. * 如果您的 PHP 没有安装 cURL 扩展,请先安装
  22. */
  23. if (!function_exists('curl_init')) {
  24. throw new Exception('OpenAPI needs the cURL PHP extension.');
  25. }
  26. /**
  27. * 如果您的 PHP 不支持JSON,请升级到 PHP 5.2.x 以上版本
  28. */
  29. if (!function_exists('json_decode')) {
  30. throw new Exception('OpenAPI needs the JSON PHP extension.');
  31. }
  32. /**
  33. * 错误码定义
  34. */
  35. define('OPENAPI_ERROR_REQUIRED_PARAMETER_EMPTY', 1801); // 参数为空
  36. define('OPENAPI_ERROR_REQUIRED_PARAMETER_INVALID', 1802); // 参数格式错误
  37. define('OPENAPI_ERROR_RESPONSE_DATA_INVALID', 1803); // 返回包格式错误
  38. define('OPENAPI_ERROR_CURL', 1900); // 网络错误, 偏移量1900, 详见 http://curl.haxx.se/libcurl/c/libcurl-errors.html
  39. /**
  40. * 提供访问腾讯开放平台 OpenApiV3 的接口
  41. */
  42. class OpenApiV3
  43. {
  44. private $appid = 0;
  45. private $appkey = '';
  46. private $server_name = '';
  47. private $format = 'json';
  48. private $stat_url = "apistat.tencentyun.com";
  49. private $is_stat = true;
  50. /**
  51. * 构造函数
  52. *
  53. * @param int $appid 应用的ID
  54. * @param string $appkey 应用的密钥
  55. */
  56. public function __construct($appid, $appkey)
  57. {
  58. $this->appid = $appid;
  59. $this->appkey = $appkey;
  60. }
  61. public function setServerName($server_name)
  62. {
  63. $this->server_name = $server_name;
  64. }
  65. public function setStatUrl($stat_url)
  66. {
  67. $this->stat_url = $stat_url;
  68. }
  69. public function setIsStat($is_stat)
  70. {
  71. $this->is_stat = $is_stat;
  72. }
  73. /**
  74. * 执行API调用,返回结果数组
  75. *
  76. * @param string $script_name 调用的API方法,比如/v3/user/get_info,参考 http://wiki.open.qq.com/wiki/API_V3.0%E6%96%87%E6%A1%A3
  77. * @param array $params 调用API时带的参数
  78. * @param string $method 请求方法 post / get
  79. * @param string $protocol 协议类型 http / https
  80. * @return array 结果数组
  81. */
  82. public function api($script_name, $params, $method = 'post', $protocol = 'http')
  83. {
  84. // 检查 openid 是否为空
  85. if (!isset($params['openid']) || empty($params['openid'])) {
  86. return array(
  87. 'ret' => OPENAPI_ERROR_REQUIRED_PARAMETER_EMPTY,
  88. 'msg' => 'openid is empty');
  89. }
  90. // 检查 openkey 是否为空
  91. if (!isset($params['openkey']) || empty($params['openkey'])) {
  92. return array(
  93. 'ret' => OPENAPI_ERROR_REQUIRED_PARAMETER_EMPTY,
  94. 'msg' => 'openkey is empty');
  95. }
  96. // 检查 openid 是否合法
  97. if (!self::isOpenId($params['openid'])) {
  98. return array(
  99. 'ret' => OPENAPI_ERROR_REQUIRED_PARAMETER_INVALID,
  100. 'msg' => 'openid is invalid');
  101. }
  102. // 无需传sig, 会自动生成
  103. unset($params['sig']);
  104. // 添加一些参数
  105. $params['appid'] = $this->appid;
  106. $params['format'] = $this->format;
  107. // 生成签名
  108. $secret = $this->appkey . '&';
  109. $sig = SnsSigCheck::makeSig($method, $script_name, $params, $secret);
  110. $params['sig'] = $sig;
  111. $url = $protocol . '://' . $this->server_name . $script_name;
  112. $cookie = array();
  113. //记录接口调用开始时间
  114. $start_time = SnsStat::getTime();
  115. //通过调用以下方法,可以打印出最终发送到openapi服务器的请求参数以及url,默认为注释
  116. //self::printRequest($url,$params,$method);
  117. // 发起请求
  118. $ret = SnsNetwork::makeRequest($url, $params, $cookie, $method, $protocol);
  119. if (false === $ret['result']) {
  120. $result_array = array(
  121. 'ret' => OPENAPI_ERROR_CURL + $ret['errno'],
  122. 'msg' => $ret['msg'],
  123. );
  124. }
  125. $result_array = json_decode($ret['msg'], true);
  126. // 远程返回的不是 json 格式, 说明返回包有问题
  127. if (is_null($result_array)) {
  128. $result_array = array(
  129. 'ret' => OPENAPI_ERROR_RESPONSE_DATA_INVALID,
  130. 'msg' => $ret['msg']
  131. );
  132. }
  133. // 统计上报
  134. if ($this->is_stat) {
  135. $stat_params = array(
  136. 'appid' => $this->appid,
  137. 'pf' => $params['pf'],
  138. 'rc' => $result_array['ret'],
  139. 'svr_name' => $this->server_name,
  140. 'interface' => $script_name,
  141. 'protocol' => $protocol,
  142. 'method' => $method,
  143. );
  144. SnsStat::statReport($this->stat_url, $start_time, $stat_params);
  145. }
  146. //通过调用以下方法,可以打印出调用openapi请求的返回码以及错误信息,默认注释
  147. //self::printRespond($result_array);
  148. return json_decode(json_encode($result_array));
  149. }
  150. /**
  151. * 执行上传文件API调用,返回结果数组
  152. *
  153. * @param string $script_name 调用的API方法,比如/v3/user/get_info, 参考 http://wiki.open.qq.com/wiki/API_V3.0%E6%96%87%E6%A1%A3
  154. * @param array $params 调用API时带的参数,必须是array
  155. * @param array $array_files 调用API时带的文件,必须是array,key为openapi接口的参数,value为"@"加上文件全路径的字符串, 举例 array('pic'=>'@/home/xxx/hello.jpg',...);
  156. * @param string $protocol 协议类型 http / https
  157. * @return array 结果数组
  158. */
  159. public function apiUploadFile($script_name, $params, $array_files, $protocol = 'http')
  160. {
  161. // 检查 openid 是否为空
  162. if (!isset($params['openid']) || empty($params['openid'])) {
  163. return array(
  164. 'ret' => OPENAPI_ERROR_REQUIRED_PARAMETER_EMPTY,
  165. 'msg' => 'openid is empty');
  166. }
  167. // 检查 openkey 是否为空
  168. if (!isset($params['openkey']) || empty($params['openkey'])) {
  169. return array(
  170. 'ret' => OPENAPI_ERROR_REQUIRED_PARAMETER_EMPTY,
  171. 'msg' => 'openkey is empty');
  172. }
  173. // 检查 openid 是否合法
  174. if (!self::isOpenId($params['openid'])) {
  175. return array(
  176. 'ret' => OPENAPI_ERROR_REQUIRED_PARAMETER_INVALID,
  177. 'msg' => 'openid is invalid');
  178. }
  179. // 无需传sig, 会自动生成
  180. unset($params['sig']);
  181. // 添加一些参数
  182. $params['appid'] = $this->appid;
  183. $params['format'] = $this->format;
  184. // 生成签名
  185. $secret = $this->appkey . '&';
  186. $sig = SnsSigCheck::makeSig('post', $script_name, $params, $secret);
  187. $params['sig'] = $sig;
  188. //上传文件,图片参数不能参与签名
  189. foreach ($array_files as $k => $v) {
  190. $params[$k] = $v;
  191. }
  192. $url = $protocol . '://' . $this->server_name . $script_name;
  193. $cookie = array();
  194. //记录接口调用开始时间
  195. $start_time = SnsStat::getTime();
  196. //通过调用以下方法,可以打印出最终发送到openapi服务器的请求参数以及url,默认注释
  197. //self::printRequest($url, $params,'post');
  198. // 发起请求
  199. $ret = SnsNetwork::makeRequestWithFile($url, $params, $cookie, $protocol);
  200. if (false === $ret['result']) {
  201. $result_array = array(
  202. 'ret' => OPENAPI_ERROR_CURL + $ret['errno'],
  203. 'msg' => $ret['msg'],
  204. );
  205. }
  206. $result_array = json_decode($ret['msg'], true);
  207. // 远程返回的不是 json 格式, 说明返回包有问题
  208. if (is_null($result_array)) {
  209. $result_array = array(
  210. 'ret' => OPENAPI_ERROR_RESPONSE_DATA_INVALID,
  211. 'msg' => $ret['msg']
  212. );
  213. }
  214. // 统计上报
  215. if ($this->is_stat) {
  216. $stat_params = array(
  217. 'appid' => $this->appid,
  218. 'pf' => $params['pf'],
  219. 'rc' => $result_array['ret'],
  220. 'svr_name' => $this->server_name,
  221. 'interface' => $script_name,
  222. 'protocol' => $protocol,
  223. 'method' => 'post',
  224. );
  225. SnsStat::statReport($this->stat_url, $start_time, $stat_params);
  226. }
  227. //通过调用以下方法,可以打印出调用openapi请求的返回码以及错误信息,默认注释
  228. //self::printRespond($result_array);
  229. return $result_array;
  230. }
  231. /**
  232. * 打印出请求串的内容,当API中的这个函数的注释放开将会被调用。
  233. *
  234. * @param string $url 请求串内容
  235. * @param array $params 请求串的参数,必须是array
  236. * @param string $method 请求的方法 get / post
  237. */
  238. private function printRequest($url, $params, $method)
  239. {
  240. $query_string = SnsNetwork::makeQueryString($params);
  241. if ($method == 'get') {
  242. $url = $url . "?" . $query_string;
  243. }
  244. echo "\n============= request info ================\n\n";
  245. print_r("method : " . $method . "\n");
  246. print_r("url : " . $url . "\n");
  247. if ($method == 'post') {
  248. print_r("query_string : " . $query_string . "\n");
  249. }
  250. echo "\n";
  251. print_r("params : " . print_r($params, true) . "\n");
  252. echo "\n";
  253. }
  254. /**
  255. * 打印出返回结果的内容,当API中的这个函数的注释放开将会被调用。
  256. *
  257. * @param array $array 待打印的array
  258. */
  259. private function printRespond($array)
  260. {
  261. echo "\n============= respond info ================\n\n";
  262. print_r($array);
  263. echo "\n";
  264. }
  265. /**
  266. * 检查 openid 的格式
  267. *
  268. * @param string $openid openid
  269. * @return bool (true|false)
  270. */
  271. private static function isOpenId($openid)
  272. {
  273. return (0 == preg_match('/^[0-9a-fA-F]{32}$/', $openid)) ? false : true;
  274. }
  275. }
  276. // end of script