GenAMSXmlFile.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. <?php
  2. namespace App\Console\Commands\Temp;
  3. use App\Modules\Book\Models\BookConfig;
  4. use App\Modules\Book\Models\Chapter;
  5. use App\Modules\Message\MessageNotify;
  6. use Illuminate\Console\Command;
  7. use Hashids;
  8. use Matrix\Exception;
  9. use OSS\OssClient;
  10. use OSS\Core\OssException;
  11. use DB;
  12. class GenAMSXmlFile extends Command
  13. {
  14. /**
  15. * The name and signature of the console command.
  16. *
  17. * @var string
  18. */
  19. protected $signature = 'gen_ams_xml_file';
  20. /**
  21. * The console command description.
  22. *
  23. * @var string
  24. */
  25. protected $description = '腾讯商品库xml生成';
  26. /**
  27. * Create a new command instance.
  28. *
  29. * @return void
  30. */
  31. public function __construct()
  32. {
  33. parent::__construct();
  34. }
  35. private $emails = [
  36. 'lisy@zw88.net',
  37. // 'songdb@iqiyoo.com',
  38. 'zhoulj@iqiyoo.com',
  39. // 'zhaoy@zw88.net'
  40. ];
  41. /**
  42. * Execute the console command.
  43. *
  44. * @return mixed
  45. */
  46. public function handle()
  47. {
  48. $this->genProductXml();
  49. }
  50. /**
  51. * genProductXml
  52. */
  53. public function genProductXml()
  54. {
  55. //筛选出上架状态为2的书籍上传
  56. $now = date('Y-m-d H:i:s');
  57. $gdt_new_bids = DB::table('gdt_new_books')->where('is_deleted', 0)->where('start_time', '<=', $now)->where('end_time', '>=', $now)->pluck('bid')->toArray();
  58. $books = BookConfig::join('books', 'book_configs.bid', '=', 'Books.id')
  59. ->leftjoin('book_categories', 'book_categories.id', 'books.category_id')
  60. ->leftjoin('chapters', 'books.last_cid', 'chapters.id')
  61. ->select(
  62. 'books.intro',
  63. 'books.status',
  64. 'books.size',
  65. 'books.chapter_count',
  66. 'books.last_chapter',
  67. 'book_configs.book_name',
  68. 'book_configs.bid',
  69. 'book_configs.cover',
  70. 'book_configs.vip_seq',
  71. 'book_configs.cover',
  72. 'book_configs.is_on_shelf',
  73. 'book_categories.id as second_category_id',
  74. 'book_categories.pid as first_category_id',
  75. 'book_categories.channel_name as first_category_name',
  76. 'book_categories.category_name as second_category_name',
  77. 'chapters.recent_update_at as latest_renew_time',
  78. 'chapters.sequence as latest_renew_chapter'
  79. )
  80. //->where('book_configs.is_on_shelf','2')
  81. ->where(function ($query) {
  82. $query->where('book_configs.is_on_shelf', '2');
  83. // ->orWhereIn('book_configs.bid', []);//豁免名单
  84. })
  85. ->get();
  86. $string = <<<XML
  87. <?xml version='1.0' encoding='utf-8'?>
  88. <product_set>
  89. </product_set>
  90. XML;
  91. $xml = new \SimpleXMLElement($string);
  92. foreach ($books as $book) {
  93. //在管理后台设置为新书的书籍标记成新书
  94. $is_new_book = in_array($book->bid, $gdt_new_bids) ? '是' : '否';
  95. $bid = Hashids::encode($book->bid);
  96. $chapters = Chapter::where('bid',$book->bid)->select('name','content','id')->orderBy('sequence')->limit(4)->get();
  97. $data =
  98. array(
  99. 'product_id' => $bid,
  100. 'product_name' => $book->book_name,
  101. 'first_category_id' => $book->first_category_id,
  102. 'second_category_id' => $book->second_category_id,
  103. 'first_category_name' => $book->first_category_name,
  104. 'second_category_name' => $book->second_category_name,
  105. 'expiration_time' => '2022-05-19 23:59:59',
  106. 'target_url_mobile' => 'https://site8y1vm7kwvv850opx.wd.amanbook.com/detail?id=' . $bid,
  107. 'target_url_wechat' => 'https://site8y1vm7kwvv850opx.wd.amanbook.com/detail?id=' . $bid,
  108. 'description' => $this->special_filter(htmlspecialchars($book->intro)),
  109. 'image_url' => $book->cover,
  110. 'word_count' => $book->size,
  111. 'serial_status' => $book->status == 1 ? '完结' : '连载',
  112. 'chapter_count' => $book->chapter_count,
  113. 'started_pay_chapter' => $book->vip_seq,
  114. 'latest_renew_time' => $book->latest_renew_time,
  115. 'latest_renew_chapter' => $book->latest_renew_chapter,
  116. 'if_new_book' => $is_new_book,
  117. 'pay_status' => '付费',
  118. );
  119. $front_chapters_data = [];
  120. foreach ($chapters as $chapter_item){
  121. $content = preg_replace("/[\n|\r\n]+/","\n",$chapter_item->content);
  122. $front_chapters_data['chapters'][] = [
  123. 'subtitle'=>htmlspecialchars($chapter_item->name),
  124. 'chapterid'=>$chapter_item->id,
  125. 'text'=>explode("\n",htmlspecialchars($content))
  126. ];
  127. }
  128. $data['book_json'] = json_encode($front_chapters_data,JSON_UNESCAPED_UNICODE);
  129. $item = $xml->addChild('product');
  130. if (is_array($data)) {
  131. foreach ($data as $key => $row) {
  132. //生成子节点
  133. try {
  134. $node = $item->addChild($key, $row);
  135. } catch (\Exception $e) {
  136. $msg = "======腾讯商品库xml生成出错=====" . date("y-m-d H:i:s" . "\n");
  137. \Log::info($msg);
  138. \Log::info($e->getMessage());
  139. $notify = MessageNotify::mail([
  140. 'to_emails' => implode(",", $this->emails),
  141. 'subject' => $msg,
  142. 'body' => $e->getMessage(),
  143. 'delay_times' => 0,
  144. ]);
  145. $notify->notify();
  146. exit();
  147. }
  148. }
  149. }
  150. }
  151. $file_path = 'storage/tx_product.xml';
  152. echo $xml->asXML($file_path);
  153. //上传到OSS
  154. $ori_file = DB::table('tencent_product_configs')->where('type', 'SITE_MAP_XML_URL')->first();
  155. $verify_code = md5_file($file_path);
  156. if ($ori_file && $ori_file->verify_code == $verify_code) {
  157. \Log::info("======腾讯商品库xml已是最新=====" . date("y-m-d H:i:s" . "\n"));
  158. } else {
  159. $file_name = 'tx_product_wdy.xml';
  160. //解析一遍看是否出错
  161. try {
  162. $load_xml = simplexml_load_file($file_path);
  163. } catch (\Exception $e) {
  164. $msg = "======腾讯商品库xml解析出错=====" . date("y-m-d H:i:s" . "\n");
  165. \Log::info($msg);
  166. \Log::info($e->getMessage());
  167. $notify = MessageNotify::mail([
  168. 'to_emails' => implode(",", $this->emails),
  169. 'subject' => $msg,
  170. 'body' => $e->getMessage(),
  171. 'delay_times' => 0,
  172. ]);
  173. $notify->notify();
  174. //删除文件以防权限问题
  175. if (file_exists($file_path)) unlink($file_path);
  176. exit();
  177. }
  178. $url = $this->saveXmlToOss($file_name, $file_path);
  179. DB::table('tencent_product_configs')
  180. ->updateOrInsert(
  181. ['type' => 'SITE_MAP_XML_URL'],
  182. [
  183. 'value' => $url,
  184. 'updated_at' => date('Y-m-d H:i:s'),
  185. 'verify_code' => $verify_code,
  186. ]
  187. );
  188. }
  189. //上传到OSS后删除,防止权限问题
  190. if (file_exists($file_path)) unlink($file_path);
  191. \Log::info("======腾讯商品库xml生成=====" . date("y-m-d H:i:s" . "\n"));
  192. return;
  193. }
  194. public function dealSpecialCharacters($char)
  195. {
  196. $char = preg_replace("[\\x00-\\x08\\x0b-\\x0c\\x0e-\\x1f]", '', $char);
  197. $char = preg_replace("/&/", '&amp', $char);
  198. $char = preg_replace("/'/", '&apos', $char);
  199. $char = preg_replace("/\"/", '&quot', $char);
  200. $char = preg_replace("/</", '&lt', $char);
  201. $char = preg_replace("/>/", '&gt', $char);
  202. return $char;
  203. }
  204. private function special_filter($string)
  205. {
  206. if (!$string) return '';
  207. $new_string = '';
  208. for ($i = 0; isset($string[$i]); $i++) {
  209. $asc_code = ord($string[$i]); //得到其asc码
  210. // 以下代码旨在过滤非法字符
  211. // ** 数值 8、9、10 和 13 可以分别转换为退格符、制表符、换行符和回车符。
  212. // 这些字符都没有图形表示,但是对于不同的应用程序,这些字符可能会影响文本的显示效果。
  213. if (in_array($asc_code, [8, 9, 10, 13], true)) {
  214. $new_string .= '';
  215. } else {
  216. $new_string .= $string[$i];
  217. }
  218. }
  219. return trim($new_string);
  220. }
  221. /**
  222. * 将xml保存到oss
  223. * @return string
  224. */
  225. function saveXmlToOss($file_name, $file)
  226. {
  227. $accessKeyId = env('OSS_ACCESS_ID');
  228. $accessKeySecret = env('OSS_ACCESS_KEY');
  229. $endpoint = env('OSS_END_POINT');
  230. $bucket = env('OSS_BUCKET');
  231. try {
  232. $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint);
  233. $upload_res = $ossClient->uploadFile($bucket, $file_name, $file);
  234. \Log::info('saveXmlToOss:'.$bucket.' $file_name:'.$file_name.' $file:'.$file);
  235. $url = str_ireplace('wangduyun.oss-cn-hangzhou.aliyuncs.com', 'cdn-novel.wd.amanbook.com', $upload_res['oss-request-url']);
  236. $url = str_ireplace('http://', 'https://', $url);
  237. } catch (OssException $e) {
  238. \Log::info($e->getMessage());
  239. }
  240. return $url;
  241. }
  242. }