Api.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. <?php
  2. /**
  3. * PHP SDK for YSDK V1.0.0
  4. */
  5. namespace huoMpay;
  6. use think\Log;
  7. /**
  8. * 如果您的 PHP 没有安装 cURL 扩展,请先安装
  9. */
  10. if (!function_exists('curl_init')) {
  11. throw new \Exception('OpenAPI needs the cURL PHP extension.');
  12. }
  13. /**
  14. * 如果您的 PHP 不支持JSON,请升级到 PHP 5.2.x 以上版本
  15. */
  16. if (!function_exists('json_decode')) {
  17. throw new \Exception('OpenAPI needs the JSON PHP extension.');
  18. }
  19. /**
  20. * 错误码定义
  21. */
  22. define('OPENAPI_ERROR_REQUIRED_PARAMETER_EMPTY', 1801); // 参数为空
  23. define('OPENAPI_ERROR_REQUIRED_PARAMETER_INVALID', 1802); // 参数格式错误
  24. define('OPENAPI_ERROR_RESPONSE_DATA_INVALID', 1803); // 返回包格式错误
  25. define('OPENAPI_ERROR_CURL', 1900); // 网络错误, 偏移量1900, 详见 http://curl.haxx.se/libcurl/c/libcurl-errors.html
  26. /**
  27. * 提供访问腾讯开放平台 YSDK 的接口
  28. */
  29. class Api {
  30. private $appid = 0;
  31. private $appkey = '';
  32. private $pay_appid = 0;
  33. private $pay_appkey = '';
  34. private $server_name = '';
  35. private $format = 'json';
  36. private $sdk_version = 'PHP YSDK v1.0.0';
  37. private $stat_url = "apistat.tencentyun.com";
  38. private $is_stat = true;
  39. /**
  40. * 构造函数
  41. *
  42. * @param int $appid 应用的ID
  43. * @param string $appkey 应用的密钥
  44. */
  45. function __construct($appid, $appkey) {
  46. $this->appid = $appid;
  47. $this->appkey = $appkey;
  48. }
  49. public function setPay($pay_appid, $pay_appkey) {
  50. $this->pay_appid = $pay_appid;
  51. $this->pay_appkey = $pay_appkey;
  52. }
  53. public function setServerName($server_name) {
  54. $this->server_name = $server_name;
  55. }
  56. /**
  57. * @return int
  58. */
  59. public function getAppid() {
  60. return $this->appid;
  61. }
  62. /**
  63. * @param int $appid
  64. */
  65. public function setAppid($appid) {
  66. $this->appid = $appid;
  67. }
  68. /**
  69. * @return string
  70. */
  71. public function getAppkey() {
  72. return $this->appkey;
  73. }
  74. /**
  75. * @param string $appkey
  76. */
  77. public function setAppkey($appkey) {
  78. $this->appkey = $appkey;
  79. }
  80. /**
  81. * @return int
  82. */
  83. public function getPayAppid() {
  84. return $this->pay_appid;
  85. }
  86. /**
  87. * @param int $pay_appid
  88. */
  89. public function setPayAppid($pay_appid) {
  90. $this->pay_appid = $pay_appid;
  91. }
  92. /**
  93. * @return string
  94. */
  95. public function getPayAppkey() {
  96. return $this->pay_appkey;
  97. }
  98. /**
  99. * @param string $pay_appkey
  100. */
  101. public function setPayAppkey($pay_appkey) {
  102. $this->pay_appkey = $pay_appkey;
  103. }
  104. /**
  105. * @return string
  106. */
  107. public function getFormat() {
  108. return $this->format;
  109. }
  110. /**
  111. * @param string $format
  112. */
  113. public function setFormat($format) {
  114. $this->format = $format;
  115. }
  116. /**
  117. * @return string
  118. */
  119. public function getSdkVersion() {
  120. return $this->sdk_version;
  121. }
  122. /**
  123. * @param string $sdk_version
  124. */
  125. public function setSdkVersion($sdk_version) {
  126. $this->sdk_version = $sdk_version;
  127. }
  128. public function setStatUrl($stat_url) {
  129. $this->stat_url = $stat_url;
  130. }
  131. public function setIsStat($is_stat) {
  132. $this->is_stat = $is_stat;
  133. }
  134. /**
  135. * 执行API调用,返回结果数组
  136. *
  137. * @param string $script_name 调用的API方法,比如/auth/verify_login,
  138. * 参考 http://wiki.dev.4g.qq.com/v2/ZH_CN/router/index.html#!qq.md#2.1 Oauth服务
  139. * @param array $params 调用API时带的参数
  140. * @param string $method 请求方法 post
  141. * @param string $protocol 协议类型 http / https
  142. *
  143. * @return array 结果数组
  144. */
  145. public function api_ysdk($script_name, $params, $method = 'post', $protocol = 'http') {
  146. // add some params: 'version'
  147. $params['version'] = $this->sdk_version;
  148. $url = $protocol.'://'.$this->server_name.$script_name;
  149. // 通过调用以下方法,可以打印出最终发送到YSDK API服务器的请求参数以及url,默认为注释
  150. self::printRequest($url, $params, $method);
  151. $cookie = array();
  152. // 发起请求
  153. $ret = SnsNetwork::makeRequest($url, $params, $cookie, $method, $protocol);
  154. if (false === $ret['result']) {
  155. $result_array = array(
  156. 'ret' => OPENAPI_ERROR_CURL + $ret['errno'],
  157. 'msg' => $ret['msg'],
  158. );
  159. } else {
  160. $result_array = json_decode($ret['msg'], true);
  161. // 远程返回的不是 json 格式, 说明返回包有问题
  162. if (is_null($result_array)) {
  163. $result_array = array(
  164. 'ret' => OPENAPI_ERROR_RESPONSE_DATA_INVALID,
  165. 'msg' => $ret['msg']
  166. );
  167. }
  168. }
  169. // 通过调用以下方法,可以打印出调用openapi请求的返回码以及错误信息,默认注释
  170. self::printRespond($result_array);
  171. return $result_array;
  172. }
  173. /**
  174. * @param $script_name
  175. * @param $accout_type
  176. * @param $params
  177. * @param string $method
  178. * @param string $protocol
  179. *
  180. * @return array|mixed
  181. */
  182. public function api_pay($script_name, $accout_type, $params, $method = 'post', $protocol = 'http') {
  183. // 添加一些参数
  184. $params['appid'] = $this->pay_appid;
  185. $params['format'] = $this->format;
  186. $cookie = array();
  187. $cookie["org_loc"] = urlencode($script_name);
  188. if ($accout_type == "qq") {
  189. $cookie["session_id"] = "openid";
  190. $cookie["session_type"] = "kp_actoken";
  191. } else if ($accout_type == "wx") {
  192. $cookie["session_id"] = "hy_gameid";
  193. $cookie["session_type"] = "wc_actoken";
  194. } else {
  195. $result_array = array(
  196. 'ret' => OPENAPI_ERROR_REQUIRED_PARAMETER_INVALID,
  197. 'msg' => '参数格式错误',
  198. );
  199. return $result_array;
  200. }
  201. // 无需传sig, 会自动生成
  202. unset($params['sig']);
  203. // 生成签名
  204. $secret = $this->pay_appkey.'&';
  205. $script_sig_name = "/v3/r".$script_name;
  206. $sig = SnsSigCheck::makeSig($method, $script_sig_name, $params, $secret);
  207. $params['sig'] = $sig;
  208. $url = $protocol.'://'.$this->server_name.$script_name;
  209. // 通过调用以下方法,可以打印出最终发送到openapi服务器的请求参数以及url,默认为注释
  210. self::printCookies($cookie);
  211. self::printRequest($url, $params, $method);
  212. // 发起请求
  213. $ret = SnsNetwork::makeRequest($url, $params, $cookie, $method, $protocol);
  214. if (false === $ret['result']) {
  215. $result_array = array(
  216. 'ret' => OPENAPI_ERROR_CURL + $ret['errno'],
  217. 'msg' => $ret['msg'],
  218. );
  219. return $result_array;
  220. }
  221. $result_array = json_decode($ret['msg'], true);
  222. // 远程返回的不是 json 格式, 说明返回包有问题
  223. if (is_null($result_array)) {
  224. $result_array = array(
  225. 'ret' => OPENAPI_ERROR_RESPONSE_DATA_INVALID,
  226. 'msg' => $ret['msg']
  227. );
  228. }
  229. // 通过调用以下方法,可以打印出调用支付API请求的返回码以及错误信息,默认注释
  230. self::printRespond($result_array);
  231. return $result_array;
  232. }
  233. /**
  234. * 打印出请求串的内容,当API中的这个函数的注释放开将会被调用。
  235. *
  236. * @param string $url 请求串内容
  237. * @param array $params 请求串的参数,必须是array
  238. * @param string $method 请求的方法 get / post
  239. */
  240. private function printRequest($url, $params, $method) {
  241. $query_string = SnsNetwork::makeQueryString($params);
  242. if ($method == 'get') {
  243. $url = $url."?".$query_string;
  244. }
  245. Log::write(
  246. "\n============= request info ================\n\n method:$method\n url:$url\n query_string:$query_string\n params:"
  247. .json_encode($params), 'error'
  248. );
  249. }
  250. /**
  251. * 打印出请求的cookies,当API中的这个函数的注释放开将会被调用。
  252. *
  253. * @param array $cookies 待打印的cookies
  254. */
  255. private function printCookies($cookies) {
  256. Log::write("\n============= printCookies ================\n\n Cookies: ".json_encode($cookies), 'error');
  257. }
  258. /**
  259. * 打印出返回结果的内容,当API中的这个函数的注释放开将会被调用。
  260. *
  261. * @param array $array 待打印的array
  262. */
  263. private function printRespond($array) {
  264. Log::write("\n============= printRespond ================\n\n Respond: ".json_encode($array), 'error');
  265. }
  266. /**
  267. * 检查 openid 的格式
  268. *
  269. * @param string $openid openid
  270. *
  271. * @return bool (true|false)
  272. */
  273. private static function isOpenId($openid) {
  274. return (0 == preg_match('/^[0-9a-fA-F]{32}$/', $openid)) ? false : true;
  275. }
  276. /**
  277. * 执行上传文件API调用,返回结果数组
  278. *
  279. * @param string $script_name 调用的API方法,比如/v3/user/get_info, 参考
  280. * http://wiki.open.qq.com/wiki/API_V3.0%E6%96%87%E6%A1%A3
  281. * @param array $params 调用API时带的参数,必须是array
  282. * @param array $array_files 调用API时带的文件,必须是array,key为openapi接口的参数,value为"@"加上文件全路径的字符串
  283. * 举例 array('pic'=>'@/home/xxx/hello.jpg',...);
  284. * @param string $protocol 协议类型 http / https
  285. *
  286. * @return array 结果数组
  287. */
  288. public function apiUploadFile($script_name, $params, $array_files, $protocol = 'http') {
  289. // 检查 openid 是否为空
  290. if (!isset($params['openid']) || empty($params['openid'])) {
  291. return array(
  292. 'ret' => OPENAPI_ERROR_REQUIRED_PARAMETER_EMPTY,
  293. 'msg' => 'openid is empty');
  294. }
  295. // 检查 openid 是否合法
  296. if (!self::isOpenId($params['openid'])) {
  297. return array(
  298. 'ret' => OPENAPI_ERROR_REQUIRED_PARAMETER_INVALID,
  299. 'msg' => 'openid is invalid');
  300. }
  301. // 无需传sig, 会自动生成
  302. unset($params['sig']);
  303. // 添加一些参数
  304. $params['appid'] = $this->appid;
  305. $params['format'] = $this->format;
  306. // 生成签名
  307. $secret = $this->appkey.'&';
  308. $sig = SnsSigCheck::makeSig('post', $script_name, $params, $secret);
  309. $params['sig'] = $sig;
  310. //上传文件,图片参数不能参与签名
  311. foreach ($array_files as $k => $v) {
  312. $params[$k] = $v;
  313. }
  314. $url = $protocol.'://'.$this->server_name.$script_name;
  315. $cookie = array();
  316. //记录接口调用开始时间
  317. $start_time = SnsStat::getTime();
  318. //通过调用以下方法,可以打印出最终发送到openapi服务器的请求参数以及url,默认注释
  319. //self::printRequest($url, $params,'post');
  320. // 发起请求
  321. $ret = SnsNetwork::makeRequestWithFile($url, $params, $cookie, $protocol);
  322. if (false === $ret['result']) {
  323. $result_array = array(
  324. 'ret' => OPENAPI_ERROR_CURL + $ret['errno'],
  325. 'msg' => $ret['msg'],
  326. );
  327. return $result_array;
  328. }
  329. $result_array = json_decode($ret['msg'], true);
  330. // 远程返回的不是 json 格式, 说明返回包有问题
  331. if (is_null($result_array)) {
  332. $result_array = array(
  333. 'ret' => OPENAPI_ERROR_RESPONSE_DATA_INVALID,
  334. 'msg' => $ret['msg']
  335. );
  336. }
  337. // 统计上报
  338. if ($this->is_stat) {
  339. $stat_params = array(
  340. 'appid' => $this->appid,
  341. 'pf' => $params['pf'],
  342. 'rc' => $result_array['ret'],
  343. 'svr_name' => $this->server_name,
  344. 'interface' => $script_name,
  345. 'protocol' => $protocol,
  346. 'method' => 'post',
  347. );
  348. SnsStat::statReport($this->stat_url, $start_time, $stat_params);
  349. }
  350. //通过调用以下方法,可以打印出调用openapi请求的返回码以及错误信息,默认注释
  351. //self::printRespond($result_array);
  352. return $result_array;
  353. }
  354. /**
  355. * 执行API调用,返回结果数组
  356. *
  357. * @param string $script_name 调用的API方法,比如/v3/user/get_info,参考
  358. * http://wiki.open.qq.com/wiki/API_V3.0%E6%96%87%E6%A1%A3
  359. * @param array $params 调用API时带的参数
  360. * @param string $method 请求方法 post / get
  361. * @param string $protocol 协议类型 http / https
  362. *
  363. * @return array 结果数组
  364. */
  365. public function api($script_name, $params, $method = 'post', $protocol = 'http') {
  366. // 检查 openid 是否为空
  367. if (!isset($params['openid']) || empty($params['openid'])) {
  368. return array(
  369. 'ret' => OPENAPI_ERROR_REQUIRED_PARAMETER_EMPTY,
  370. 'msg' => 'openid is empty');
  371. }
  372. // 检查 openid 是否合法
  373. if (!self::isOpenId($params['openid'])) {
  374. return array(
  375. 'ret' => OPENAPI_ERROR_REQUIRED_PARAMETER_INVALID,
  376. 'msg' => 'openid is invalid');
  377. }
  378. // 无需传sig, 会自动生成
  379. unset($params['sig']);
  380. // 添加一些参数
  381. $params['appid'] = $this->appid;
  382. $params['format'] = $this->format;
  383. // 生成签名
  384. $secret = $this->appkey.'&';
  385. $sig = SnsSigCheck::makeSig($method, $script_name, $params, $secret);
  386. $params['sig'] = $sig;
  387. $url = $protocol.'://'.$this->server_name.$script_name;
  388. self::printRequest($url, $params, $method);
  389. $cookie = array();
  390. //记录接口调用开始时间
  391. $start_time = SnsStat::getTime();
  392. //通过调用以下方法,可以打印出最终发送到openapi服务器的请求参数以及url,默认为注释
  393. //self::printRequest($url,$params,$method);
  394. // 发起请求
  395. $ret = SnsNetwork::makeRequest($url, $params, $cookie, $method, $protocol);
  396. if (false === $ret['result']) {
  397. $result_array = array(
  398. 'ret' => OPENAPI_ERROR_CURL + $ret['errno'],
  399. 'msg' => $ret['msg'],
  400. );
  401. return $result_array;
  402. }
  403. $result_array = json_decode($ret['msg'], true);
  404. // 远程返回的不是 json 格式, 说明返回包有问题
  405. if (is_null($result_array)) {
  406. $result_array = array(
  407. 'ret' => OPENAPI_ERROR_RESPONSE_DATA_INVALID,
  408. 'msg' => $ret['msg']
  409. );
  410. }
  411. // 统计上报
  412. if ($this->is_stat) {
  413. $stat_params = array(
  414. 'appid' => $this->appid,
  415. 'pf' => $params['pf'],
  416. 'rc' => $result_array['ret'],
  417. 'svr_name' => $this->server_name,
  418. 'interface' => $script_name,
  419. 'protocol' => $protocol,
  420. 'method' => $method,
  421. );
  422. SnsStat::statReport($this->stat_url, $start_time, $stat_params);
  423. }
  424. //通过调用以下方法,可以打印出调用openapi请求的返回码以及错误信息,默认注释
  425. //self::printRespond($result_array);
  426. return $result_array;
  427. }
  428. }
  429. // end of script