dms_edoc.class.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. <?php
  2. if (!defined('IN_ONLINE')) {
  3. exit('Access Denied');
  4. }
  5. /**
  6. * Description of dms_edoc
  7. *
  8. * @author Administrator
  9. */
  10. class dms_edoc {
  11. private static $cachedToken = null;
  12. private static $tokenExpiryTime = 0;
  13. private static $oceanMapping = [
  14. 'P' => 'PKL',
  15. 'QO' => 'QOF',
  16. 'Z' => '',
  17. 'S' => 'ISF',
  18. 'H' => 'HBL',
  19. 'CON' => 'CON',
  20. 'M' => 'MBL',
  21. 'O' => 'DOR',
  22. 'PU' => '',
  23. 'C' => 'CRD',
  24. 'F' => 'FRL',
  25. 'D' => 'OTH',
  26. 'RUT' => 'INS',
  27. 'CNEEA' => '',
  28. 'MF1' => 'CMS',
  29. 'CNEEV' => '',
  30. 'A' => 'ARN',
  31. 'COO' => 'COO',
  32. 'I' => 'CIV',
  33. 'V' => '',
  34. 'B' => 'OTH',
  35. 'CRD' => 'CUD',
  36. 'BC' => 'BCF',
  37. 'DCIV' => 'CIV',
  38. 'DPKGLIST' => 'PKL',
  39. 'TIV' => 'DBN',
  40. 'MIV' => '',
  41. 'DA' => 'DLA',
  42. 'CPV' => '',
  43. 'BE' => 'BOE',
  44. 'Q' => 'QOF',
  45. 'SO' => 'SSO',
  46. 'WCR' => 'WCR',
  47. 'DG' => 'DGC',
  48. 'PL-LEN' => '',
  49. 'CCO' => 'CCO',
  50. 'DN' => 'DBN',
  51. 'NPRS' => 'NPS',
  52. 'SOP' => 'SOP',
  53. 'TD' => 'TAX',
  54. 'BI' => 'BIS',
  55. 'CRL' => 'CUR',
  56. 'PRF' => 'PRF',
  57. 'SCIV' => 'SCV',
  58. 'JC' => 'PNL',
  59. 'TELEX' => 'TLX',
  60. 'CN' => 'CRN',
  61. 'DGD' => 'DGC',
  62. 'CPS' => 'CPS',
  63. 'SPIV' => 'SIV',
  64. 'CSI' => 'CSI',
  65. 'MSTY' => 'DGC',
  66. 'CLP' => 'CLP',
  67. 'DD' => 'DND',
  68. 'PA' => 'PAL',
  69. 'JS' => 'IBI',
  70. 'TCR' => 'TCR',
  71. 'T' => '',
  72. 'OFT' => 'OFT',
  73. 'CM' => 'PCD',
  74. 'DUT' => 'DUT',
  75. 'EIR' => 'EIR',
  76. 'MS' => 'BMS',
  77. 'ECLR' => 'ECL',
  78. 'CPA' => 'CPA',
  79. 'SOC' => 'SOC',
  80. 'CP' => 'CPG',
  81. 'PSJS' => 'FRL',
  82. 'CI' => 'SIV',
  83. 'CPC' => 'CPC',
  84. 'DBL' => 'DBL',
  85. 'PNL' => 'PNL',
  86. 'POD' => 'POD',
  87. 'MD' => 'DES',
  88. 'SWB' => 'HBL',
  89. 'SC' => 'SCC',
  90. 'TO' => 'TSO',
  91. 'WO' => 'TSO',
  92. 'DR' => 'DKR',
  93. 'RM' => '',
  94. 'FCR' => 'FCR',
  95. 'BS' => 'BSL',
  96. 'TM' => '',
  97. 'FCLP' => 'CLP',
  98. 'SRD' => 'SRD',
  99. 'SLI' => 'SLI',
  100. 'SSI' => 'SSI',
  101. 'VGM' => 'VGM',
  102. 'SLG' => 'SLG',
  103. 'ICLR' => 'ICL',
  104. ];
  105. private static $airMapping = [
  106. 'M' => 'MBL',
  107. 'H' => 'HBL',
  108. 'S' => 'ISF',
  109. 'DG' => 'DGC',
  110. 'CRL' => 'CUR',
  111. 'O' => 'DOR',
  112. 'D' => 'OTH',
  113. 'TD' => 'TAX',
  114. 'T' => 'CRD',
  115. 'C' => '',
  116. 'SOP' => 'SOP',
  117. 'CCO' => 'CCO',
  118. 'A' => 'ARN',
  119. 'MF' => '',
  120. 'F' => 'FRL',
  121. 'BE' => 'BOE',
  122. 'NPRS' => 'NPS',
  123. 'FCR' => 'FCR',
  124. 'VGM' => 'VGM',
  125. 'CON' => 'CON',
  126. 'JS' => 'IBI',
  127. 'HB' => 'HBL',
  128. 'SPIV' => 'SIV',
  129. 'WCR' => 'WCR',
  130. 'APRHB' => 'HBL',
  131. 'B' => 'OTH',
  132. 'TCR' => 'TCR',
  133. 'CLP' => 'CLP',
  134. 'MAB' => 'MBL',
  135. 'DAB' => 'DBL',
  136. 'TELEX' => 'TLX',
  137. 'I' => 'o',
  138. 'P' => 'PKL',
  139. 'SLG' => 'SLG',
  140. 'QO' => 'QOF',
  141. 'SC' => 'SCC',
  142. 'CPV' => 'PRF',
  143. 'SO' => 'SSO',
  144. 'FCLP' => 'CLP',
  145. 'PNL' => 'dg',
  146. 'TM' => '',
  147. 'MSTY' => 'DGC',
  148. 'POD' => 'POD',
  149. 'DR' => 'DKR',
  150. 'RM' => '',
  151. 'DBL' => 'DBL',
  152. 'CSI' => 'CSI',
  153. 'ICLR' => 'ICL',
  154. 'ECLR' => 'ECL',
  155. 'MD' => 'DES',
  156. 'CP' => 'CPG',
  157. 'CPS' => 'CPS',
  158. 'CPA' => 'CPA',
  159. 'CPC' => 'CPC',
  160. 'TO' => 'TSO',
  161. 'SCIV' => 'SCV',
  162. 'PR' => 'PRF',
  163. 'DA' => 'DLA',
  164. 'MS' => 'BMS',
  165. 'DGD' => 'DGC',
  166. 'PLLEN' => '',
  167. 'SLI' => 'SLI',
  168. 'MIV' => '',
  169. 'PSJS' => 'FRL',
  170. 'TIV' => 'DBN',
  171. 'DPKGLIST' => 'PKL',
  172. 'DCIV' => 'CIV',
  173. 'BC' => 'BCF',
  174. 'SWB' => 'HBL',
  175. 'SSI' => 'SSI',
  176. 'BI' => 'BIS',
  177. 'JC' => 'PNL',
  178. 'AL' => 'ALL',
  179. 'BS' => 'BSL',
  180. 'WO' => 'TSO',
  181. 'PA' => 'PAL',
  182. ];
  183. /**
  184. * 获取文件List
  185. */
  186. public static function getEdocFile($hbol,$docTypes,$oceanAir){
  187. try {
  188. $result = null;
  189. //old code => Doc_Code
  190. $mapping = $oceanAir == "ocean" ? self::$oceanMapping : self::$airMapping;
  191. $resultDocTypes = array_values(array_filter(
  192. array_map(
  193. fn($type) => $mapping[$type] ?? null,
  194. $docTypes
  195. ),
  196. fn($mapped) => !empty($mapped) // 过滤 null 和空字符串
  197. ));
  198. $data = [
  199. 'fromStation' => '',
  200. 'hbol' => $hbol,
  201. 'docTypes' => $resultDocTypes
  202. ];
  203. // $data = [
  204. // 'fromStation' => '',
  205. // 'hbol' => 'ABCNA1008776',
  206. // 'docTypes' => ["WO"]
  207. // ];
  208. $accessTokenUrl = 'http://dms.kln.com/keycloak/realms/dsms-realm/protocol/openid-connect/token';
  209. //prod 账号
  210. $grant_type = 'client_credentials';
  211. $client_id = 'online';
  212. $client_secret = 'ouuRZ8QbIrcqKZi0NBJLt7PUEiRr5uXd';
  213. $accessToken = dms_edoc::getAccessToken($accessTokenUrl,$grant_type,$client_id,$client_secret);
  214. if ($accessToken === null) {
  215. throw new Exception("Failed to obtain access token");
  216. }
  217. $New_Dms_Url = 'http://dms.kln.com/edoc/documents/fileList';
  218. $result = dms_edoc::CURLClient($New_Dms_Url,$accessToken,$data);
  219. } catch (Exception $e) {
  220. error_log("Error getEdocFile: " . $e->getMessage());
  221. }
  222. return $result;
  223. }
  224. /**
  225. * 下载文件byoutId
  226. */
  227. public static function downloadEdocFile($outId,$display_name){
  228. try {
  229. $result = null;
  230. $data = ['outId' => $outId];
  231. $accessTokenUrl = 'http://dms.kln.com/keycloak/realms/dsms-realm/protocol/openid-connect/token';
  232. //prod 账号
  233. $grant_type = 'client_credentials';
  234. $client_id = 'online';
  235. $client_secret = 'ouuRZ8QbIrcqKZi0NBJLt7PUEiRr5uXd';
  236. $accessToken = dms_edoc::getAccessToken($accessTokenUrl,$grant_type,$client_id,$client_secret);
  237. if ($accessToken === null) {
  238. throw new Exception("Failed to obtain access token");
  239. }
  240. $New_Dms_Url = 'http://dms.kln.com/storagesrv/files/download/edoc/downloadByOutId';
  241. dms_edoc::CURLClientDownload($New_Dms_Url,$accessToken,$data,$display_name);
  242. } catch (Exception $e) {
  243. error_log("Error getEdocFile: " . $e->getMessage());
  244. }
  245. }
  246. public static function getAccessToken($accessTokenUrl,$grant_type,$client_id,$client_secret){
  247. //还是需要这个,如果在一个请求里多次调用这个方法的话,就可以用缓存的
  248. if (self::$cachedToken !== null && time() * 1000 < self::$tokenExpiryTime) {
  249. return self::$cachedToken;
  250. }
  251. $postData = http_build_query([
  252. 'grant_type' => $grant_type,
  253. 'client_id' => $client_id,
  254. 'client_secret' => $client_secret
  255. ]);
  256. $headers = [
  257. 'Content-Type: application/x-www-form-urlencoded',
  258. 'Accept: application/json'
  259. ];
  260. $curlInit = curl_init();
  261. curl_setopt_array($curlInit, [
  262. CURLOPT_URL => $accessTokenUrl,
  263. CURLOPT_POST => true,
  264. CURLOPT_POSTFIELDS => $postData,
  265. CURLOPT_HTTPHEADER => $headers,
  266. CURLOPT_RETURNTRANSFER => true, // 关键!返回字符串而不是输出
  267. CURLOPT_SSL_VERIFYPEER => false, // 生产环境建议开启
  268. CURLOPT_TIMEOUT => 30,
  269. CURLOPT_HEADER => false, // 不返回 header
  270. ]);
  271. $response = curl_exec($curlInit);
  272. $httpCode = curl_getinfo($curlInit, CURLINFO_HTTP_CODE);
  273. // 关闭 cURL
  274. curl_close($curlInit);
  275. // 解析响应
  276. if ($httpCode === 200) {
  277. $jsonResponse = json_decode($response, true);
  278. if (isset($jsonResponse['access_token'])) {
  279. self::$cachedToken = $jsonResponse['access_token'];
  280. $expiresIn = isset($jsonResponse['expires_in']) ?
  281. $jsonResponse['expires_in'] * 1000 : 600 * 1000;
  282. self::$tokenExpiryTime = (time() * 1000) + $expiresIn - 300000;
  283. return self::$cachedToken;
  284. }
  285. }
  286. //如果是这里返回,说明Token请求失败
  287. self::$cachedToken = null;
  288. self::$tokenExpiryTime = 0;
  289. return null;
  290. }
  291. /**
  292. * 使用 cURL 获取文件list
  293. */
  294. public static function CURLClient($url,$accessToken,$data){
  295. $headers = [
  296. 'Authorization: Bearer ' . $accessToken,
  297. 'Content-Type: application/json',
  298. 'Accept: ' . 'application/json'
  299. ];
  300. //$url = 'http://dsms-alb-internet-facing-449737170.ap-southeast-1.elb.amazonaws.com/edoc/documents/fileList';
  301. //$url = 'http://dms.kln.com/edoc/documents/fileList';
  302. // 将数据编码为 JSON
  303. $jsonData = json_encode($data);
  304. try {
  305. $curlInit = curl_init();
  306. curl_setopt_array($curlInit, [
  307. CURLOPT_URL => $url,
  308. CURLOPT_POST => true,
  309. CURLOPT_POSTFIELDS => $jsonData,
  310. CURLOPT_HTTPHEADER => $headers,
  311. CURLOPT_RETURNTRANSFER => true, // 关键!返回字符串而不是输出
  312. CURLOPT_SSL_VERIFYPEER => false, // 生产环境建议开启
  313. CURLOPT_TIMEOUT => 30,
  314. CURLOPT_HEADER => false, // 不返回 header
  315. ]);
  316. $response = curl_exec($curlInit);
  317. // 检查是否有错误
  318. if ($response === false) {
  319. $error = curl_error($curlInit);
  320. error_log("cURL 请求失败: " . $error);
  321. throw new Exception("cURL 请求失败: " . $error);
  322. }
  323. // 获取 HTTP 状态码
  324. $httpCode = curl_getinfo($curlInit, CURLINFO_HTTP_CODE);
  325. // 关闭 cURL
  326. curl_close($curlInit);
  327. // 解析响应
  328. $result = json_decode($response, true);
  329. if ($httpCode == 200 && isset($result['data'])) {
  330. return json_encode($result['data'], JSON_UNESCAPED_UNICODE);
  331. }
  332. } catch (Exception $e) {
  333. error_log($e->getMessage());
  334. }
  335. return null;
  336. }
  337. /**
  338. * 使用 cURL 下载文件
  339. */
  340. public static function CURLClientDownload($url,$accessToken,$data,$filename){
  341. $headers = [
  342. 'Authorization: Bearer ' . $accessToken,
  343. 'Content-Type: application/json'
  344. ];
  345. // 将数据编码为 JSON
  346. $jsonData = json_encode($data);
  347. try {
  348. $curlInit = curl_init();
  349. curl_setopt_array($curlInit, [
  350. CURLOPT_URL => $url,
  351. CURLOPT_POST => true,
  352. CURLOPT_POSTFIELDS => $jsonData,
  353. CURLOPT_HTTPHEADER => $headers,
  354. CURLOPT_RETURNTRANSFER => true, // 关键!返回字符串而不是输出
  355. CURLOPT_SSL_VERIFYPEER => false, // 生产环境建议开启
  356. CURLOPT_TIMEOUT => 30,
  357. CURLOPT_HEADER => false, // 不返回 header
  358. ]);
  359. $response = curl_exec($curlInit);
  360. // 检查是否有错误
  361. if ($response === false) {
  362. $error = curl_error($curlInit);
  363. error_log("cURL 请求失败: " . $error);
  364. throw new Exception("cURL 请求失败: " . $error);
  365. }
  366. // 获取 HTTP 状态码
  367. $httpCode = curl_getinfo($curlInit, CURLINFO_HTTP_CODE);
  368. // 关闭 cURL
  369. curl_close($curlInit);
  370. // 判断响应是否是 JSON(通常是错误信息)
  371. $isJson = false;
  372. $jsonResponse = json_decode($response, true);
  373. if (json_last_error() === JSON_ERROR_NONE && isset($jsonResponse['status'])) {
  374. $isJson = true;
  375. }
  376. if ($isJson) {
  377. // 是错误响应
  378. if ($jsonResponse['status'] === 'FAILED') {
  379. // 是 DMS 返回的错误
  380. http_response_code(404);
  381. header('Content-Type: application/json; charset=utf-8');
  382. echo json_encode([
  383. 'error' => $jsonResponse['message'] ?? 'Document not found',
  384. 'code' => $jsonResponse['code'] ?? 'download_error'
  385. ], JSON_UNESCAPED_UNICODE);
  386. return;
  387. }
  388. } else {
  389. // 直接当作 ZIP 下载
  390. while (ob_get_level()) ob_end_clean();
  391. //header("Content-Type: application/pdf");
  392. header("Content-type:" . common::getContentType($filename));
  393. header("Content-Length: " . strlen($response));
  394. header("Content-Disposition: attachment; filename=\"" . rawurlencode($filename) . "\"; filename*=UTF-8''" . rawurlencode($filename));
  395. header("Cache-Control: no-cache, must-revalidate");
  396. header("Pragma: public");
  397. echo $response;
  398. exit;
  399. }
  400. } catch (Exception $e) {
  401. error_log($e->getMessage());
  402. }
  403. }
  404. }
  405. ?>