优惠券小程序

GoodsService.php 20KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: shensong
  5. * Date: 2022/10/14
  6. * Time: 17:48
  7. */
  8. namespace App\Service;
  9. use App\Log;
  10. use App\Models\Redis\RedisModel;
  11. use App\Models\UserInterestGoods;
  12. use App\Support\HaoDanKuApi;
  13. use App\Support\TaoBaoApi;
  14. class GoodsService
  15. {
  16. public static function salesTypeList()
  17. {
  18. return [
  19. ['title' => '好货推荐', 'value' => 1],
  20. ['title' => '今日搜榜', 'value' => 2],
  21. ];
  22. }
  23. public static function salesList($minId, $pageSize, $saleType)
  24. {
  25. # 获取本接口推广位ID
  26. $promotionId = GoodsCommonService::getPromotionId();
  27. # 请求数据
  28. $list = HaoDanKuApi::sales_list($saleType, $minId, $pageSize);
  29. $redisKey = 'yhq-smallapp::salesList-'.$saleType.'-'.$minId.'-'.$pageSize;
  30. # 将推广位ID拼接进去
  31. if(isset($list['code']) && 1 == $list['code']) {
  32. RedisModel::set($redisKey, json_encode($list, 256));
  33. RedisModel::expire($redisKey, 7*86400);# 缓存7天
  34. } else {
  35. $redisValue = RedisModel::get($redisKey);
  36. if(!empty($redisValue)) {
  37. $redisValue = json_decode($redisValue, 1);
  38. $list = $redisValue;
  39. }
  40. }
  41. $fieldMapping = HaoDanKuApi::fieldMapping();
  42. $res = [];
  43. # 处理图片链接等信息
  44. if(isset($list['data']) && !empty($list['data'])){
  45. foreach($list['data'] as $value) {
  46. $item = [];
  47. foreach($value as $k=>$v) {
  48. $newKey = $fieldMapping[$k] ?? null;
  49. if(!empty($newKey)) {
  50. $item[$newKey] = $v;
  51. }
  52. }
  53. $item['item_pic'] = isset($item['item_pic']) ? $item['item_pic'].'_310x310.jpg' : '';
  54. $item['promotion_id'] = $promotionId;
  55. $item['shop_type'] = GoodsCommonService::getShopType($item['shop_type'], 1);
  56. $res[] = $item;
  57. }
  58. }
  59. $data = [
  60. 'data' => $res,
  61. 'min_id' => $list['min_id'] ?? null,
  62. ];
  63. return $data;
  64. }
  65. public static function excellentEditor($minId, $pageSize)
  66. {
  67. # 获取本接口推广位ID
  68. $promotionId = GoodsCommonService::getPromotionId();
  69. # 请求数据
  70. $list = HaoDanKuApi::excellent_editor($minId, $pageSize);
  71. $redisKey = 'yhq-smallapp::excellentEditor-'.$minId.'-'.$pageSize;
  72. # 将推广位ID拼接进去
  73. if(isset($list['code']) && 1 == $list['code']) {
  74. RedisModel::set($redisKey, json_encode($list, 256));
  75. RedisModel::expire($redisKey, 7*86400);# 缓存7天
  76. } else {
  77. $redisValue = RedisModel::get($redisKey);
  78. if(!empty($redisValue)) {
  79. $redisValue = json_decode($redisValue, 1);
  80. $list = $redisValue;
  81. }
  82. }
  83. $fieldMapping = HaoDanKuApi::fieldMapping();
  84. $itemIdList = [];
  85. $res = [];
  86. # 处理图片链接等信息
  87. if(isset($list['data']) && !empty($list['data'])){
  88. foreach($list['data'] as $value) {
  89. $item = [];
  90. foreach($value as $k=>$v) {
  91. $newKey = $fieldMapping[$k] ?? null;
  92. if(!empty($newKey)) {
  93. $item[$newKey] = $v;
  94. }
  95. }
  96. $item['item_pic'] = isset($item['item_pic']) ? $item['item_pic'].'_310x310.jpg' : '';
  97. $item['time'] = isset($item['time']) ? date('Y-m-d H:i:s', $item['time']) : '';
  98. $item['copy_text'] = str_replace("&lt;br&gt;", '<br>', $item['copy_text']);
  99. $item['promotion_id'] = $promotionId;
  100. $item['shop_type'] = GoodsCommonService::getShopType($item['shop_type'], 1);
  101. $itemIdList[] = $item['item_id'];
  102. $res[] = $item;
  103. }
  104. }
  105. # 优选接口不会返回商品标题,只有短标题,需要额外通过查询商品详情页获取商品标题
  106. if(count($itemIdList) <= 10) {
  107. $itemIdList = implode(',', $itemIdList);
  108. $itemInfoList = self::itemDetail($itemIdList, $promotionId);
  109. $itemTitleList = [];
  110. foreach($itemInfoList as $value) {
  111. $itemTitleList[$value['item_id']] = $value['item_title'];
  112. }
  113. } else {
  114. $itemIdArr = array_chunk($itemIdList, 10);
  115. $itemTitleList = [];
  116. foreach($itemIdArr as $items) {
  117. $items = implode(',', $items);
  118. $itemInfoList = self::itemDetail($items, $promotionId);
  119. foreach($itemInfoList as $value) {
  120. $itemTitleList[$value['item_id']] = $value['item_title'];
  121. }
  122. }
  123. }
  124. foreach($res as $k=>$v) {
  125. $res[$k]['item_title'] = $itemTitleList[$v['item_id']] ?? '';
  126. }
  127. $data = [
  128. 'data' => $res,
  129. 'min_id' => $list['min_id'] ?? null,
  130. ];
  131. return $data;
  132. }
  133. public static function goodsSearch($userId, $minId, $pageSize, $keyword, $isCoupon, $sortNum, $tbP, $pageNo)
  134. {
  135. # 记录用户搜索关键词
  136. UserService::userSearch($keyword, $userId);
  137. # 获取本接口推广位ID
  138. $promotionId = GoodsCommonService::getPromotionId();
  139. # 好单库
  140. $list = GoodsService::superSearch($minId, $pageSize, $keyword, $isCoupon, $sortNum, $tbP, $promotionId);
  141. if(empty($list)) {
  142. # 淘宝客
  143. $list = GoodsService::materialSearch($minId, $pageSize, $keyword, $isCoupon, $sortNum, $tbP, $pageNo, $promotionId);
  144. }
  145. return $list;
  146. }
  147. # 好单库 淘宝超级搜索API
  148. public static function superSearch($minId, $pageSize, $keyword, $isCoupon, $sortNum, $tbP, $promotionId)
  149. {
  150. # 处理排序字段
  151. switch($sortNum){
  152. case 1: $sort = 0; break; // 综合
  153. case 2: $sort = 2; break; // 销量高到低
  154. case 3: $sort = 4; break; // 价格低到高
  155. case 4: $sort = 5; break; // 价格高到低
  156. default:$sort = 0; break;
  157. }
  158. $list = HaoDanKuApi::supersearch($keyword, null, $minId, $pageSize, $tbP, $sort, null, $isCoupon);
  159. $fieldMapping = HaoDanKuApi::fieldMapping();
  160. $data = [];
  161. if(isset($list['code']) && 1 == $list['code']) {
  162. $res = [];
  163. # 处理图片链接
  164. if(isset($list['data']) && !empty($list['data'])){
  165. foreach($list['data'] as $value) {
  166. $item = [];
  167. foreach($value as $k=>$v) {
  168. $newKey = $fieldMapping[$k] ?? null;
  169. if(!empty($newKey)) {
  170. $item[$newKey] = $v;
  171. }
  172. }
  173. $item['item_pic'] = isset($item['item_pic']) ? $item['item_pic'].'_310x310.jpg' : '';
  174. $item['promotion_id'] = $promotionId;
  175. $item['shop_type'] = GoodsCommonService::getShopType($item['shop_type'], 1);
  176. $res[] = $item;
  177. }
  178. }
  179. $data = [
  180. 'data' => $res,
  181. 'min_id' => $list['min_id'] ?? null,
  182. 'tb_p' => $list['tb_p'] ?? null,
  183. ];
  184. }
  185. return $data;
  186. }
  187. # 淘宝联盟 物料搜索API
  188. public static function materialSearch($startId, $pageSize, $keyword, $isCoupon, $sortNum, $tbP, $pageNo, $promotionId)
  189. {
  190. $method = 'taobao.tbk.dg.material.optional';
  191. $paramsArr['page_size'] = $pageSize;
  192. $paramsArr['q'] = $keyword;
  193. // $paramsArr['page_result_key'] = $tbP;
  194. $paramsArr['adzone_id'] = '114488850210';
  195. $paramsArr['page_no'] = $pageNo;
  196. if(!empty($promotionId)){
  197. $arr = explode('_', $promotionId);
  198. $paramsArr['adzone_id'] = $arr[3] ?? $paramsArr['adzone_id'];
  199. }
  200. switch($sortNum){
  201. case 1: break;// 综合
  202. case 2: $paramsArr['sort'] = 'total_sales_des'; break;// 销量从高到低
  203. case 3: $paramsArr['sort'] = 'price_asc'; break;// 价格低到高
  204. case 4: $paramsArr['sort'] = 'price_des'; break;// 价格高到低
  205. default: break;
  206. }
  207. if(1 == $isCoupon) {
  208. $paramsArr['has_coupon'] = true;
  209. }
  210. $data = TaoBaoApi::createRequest($method, $paramsArr);
  211. $list = $data['tbk_dg_material_optional_response']['result_list']['map_data'] ?? [];
  212. $total = $data['tbk_dg_material_optional_response']['total_results'] ?? 0;
  213. $pageResultKey = $data['tbk_dg_material_optional_response']['page_result_key'] ?? null;
  214. $fieldMapping = TaoBaoApi::fieldMapping();
  215. $res = [];
  216. foreach($list as $value) {
  217. $item = [];
  218. foreach($value as $k=>$v) {
  219. $newKey = $fieldMapping[$k] ?? null;
  220. if(!empty($newKey)) {
  221. $item[$newKey] = $v;
  222. }
  223. }
  224. $item['shop_type'] = GoodsCommonService::getShopType($item['shop_type'], 2);
  225. $item['item_price'] = isset($item['zk_final_price']) ? $item['zk_final_price'] :
  226. (isset($item['item_price']) ? $item['item_price'] : 0);
  227. $item['item_end_price'] = (isset($item['coupon_money']) && $item['item_price'] > 0) ?
  228. $item['item_price'] - $item['coupon_money'] : $item['item_price'];
  229. $item['promotion_id'] = $promotionId;
  230. $res[] = $item;
  231. }
  232. $data = [
  233. 'data' => $res,
  234. 'min_id' => null,
  235. 'tb_p' => $pageResultKey,
  236. ];
  237. return $data;
  238. }
  239. public static function goodsDetail($itemId, $promotionId, $userId=null, $isMultiple = null)
  240. {
  241. # 处理商品ID
  242. if(is_array($itemId)) {
  243. $itemId = implode(',', $itemId);
  244. }
  245. # 好单库
  246. $data = GoodsService::itemDetail($itemId, $promotionId);
  247. if(empty($data) && !$isMultiple) {
  248. # 淘宝客
  249. $data = GoodsService::itemInfo($itemId, $promotionId);
  250. }
  251. # 判断商品是否已收藏
  252. if(!$isMultiple) {
  253. $hadCollect = UserInterestGoods::hadInterest($userId, $itemId);
  254. $data['is_collect'] = $hadCollect ? 1 : 0;
  255. }
  256. return $data;
  257. }
  258. # 好单库商品详情
  259. public static function itemDetail($itemId, $promotionId)
  260. {
  261. # 请求数据
  262. $res = HaoDanKuApi::item_detail($itemId);
  263. $data = [];
  264. if(isset($res['code']) && 1 == $res['code']) {
  265. $fieldMapping = HaoDanKuApi::fieldMapping();
  266. # 单独一个商品信息
  267. if(!empty($res['data'])) {
  268. foreach($res['data'] as $k=>$v) {
  269. $newKey = $fieldMapping[$k] ?? null;
  270. if(!empty($newKey)) {
  271. $data[$newKey] = $v;
  272. }
  273. }
  274. $data['shop_type'] = GoodsCommonService::getShopType($data['shop_type'], 1);
  275. $data['item_pic'] = !empty($data['item_pic']) ? $data['item_pic'].'_310x310.jpg' : '';
  276. $data['item_pic_copy'] = !empty($data['item_pic_copy']) ? 'http://img-haodanku-com.cdn.fudaiapp.com/'.$data['item_pic_copy'] : '';
  277. $data['taobao_image'] = !empty($data['taobao_image']) ? explode(',', $data['taobao_image']) : [];
  278. $data['video_url'] = (!empty($data['video_id']) && $data['video_id'] > 0) ?
  279. 'http://cloud.video.taobao.com/play/u/1/p/1/e/6/t/1/' . $data['video_id'] . '.mp4' : '';
  280. $data['item_title'] = $data['item_title'] ?? '';
  281. # 单个商品调取时才会直接返回淘口令
  282. $taoWordInfo = self::createTaobaoWord($itemId, $promotionId, $data['item_title']);
  283. $data['taoword'] = $taoWordInfo['taoword'];
  284. $data['model'] = $taoWordInfo['model'];
  285. # 判断返回的商品ID是否与请求商品ID一致
  286. if($itemId != $data['item_id']) {
  287. $data['item_id'] = $itemId;
  288. }
  289. }
  290. # 一次返回多个商品信息
  291. if(!empty($res['all_data'])) {
  292. $itemIdArr = explode(',', $itemId);
  293. foreach($res['all_data'] as $value) {
  294. $item = [];
  295. foreach($value as $k=>$v) {
  296. $newKey = $fieldMapping[$k] ?? null;
  297. if(!empty($newKey)) {
  298. $item[$newKey] = $v;
  299. }
  300. }
  301. $item['shop_type'] = GoodsCommonService::getShopType($item['shop_type'], 1);
  302. $item['item_pic'] = !empty($item['item_pic']) ? $item['item_pic'].'_310x310.jpg' : '';
  303. $item['item_pic_copy'] = !empty($item['item_pic_copy']) ? 'http://img-haodanku-com.cdn.fudaiapp.com/'.$item['item_pic_copy'] : '';
  304. $item['taobao_image'] = !empty($item['taobao_image']) ? explode(',', $item['taobao_image']) : [];
  305. $item['video_url'] = (!empty($item['video_id']) && $item['video_id'] > 0) ?
  306. 'http://cloud.video.taobao.com/play/u/1/p/1/e/6/t/1/' . $item['video_id'] . '.mp4' : '';
  307. if(!in_array($item['item_id'], $itemIdArr)) {
  308. continue;
  309. }
  310. $data[] = $item;
  311. }
  312. }
  313. }
  314. return $data;
  315. }
  316. # 淘宝客商品详情
  317. public static function itemInfo($itemId, $promotionId)
  318. {
  319. $method = 'taobao.tbk.item.info.get';
  320. $paramsArr['num_iids'] = $itemId;
  321. $res = TaoBaoApi::createRequest($method, $paramsArr);
  322. $list = $res['tbk_item_info_get_response']['results']['n_tbk_item'] ?? [];
  323. $fieldMapping = TaoBaoApi::fieldMapping();
  324. $data = [];
  325. foreach($list as $value) {
  326. $item = [];
  327. foreach($value as $k=>$v) {
  328. $newKey = $fieldMapping[$k] ?? null;
  329. if(!empty($newKey)) {
  330. $item[$newKey] = $v;
  331. }
  332. }
  333. $item['item_pic_copy'] = '';
  334. $item['taobao_image'] = $item['taobao_image']['string'] ?? [];
  335. $item['video_url'] = '';
  336. $item['is_live'] = 0;
  337. $item['shop_type'] = GoodsCommonService::getShopType($item['shop_type'], 1);
  338. # 查询商品券信息
  339. $keyword = GoodsCommonService::getTaobaoUrl($itemId);
  340. $itemInfo = GoodsService::materialSearch(null, 1, $keyword, null, 1, null, 1, $promotionId);
  341. // Log::info('test', $itemInfo, 'test_ss');
  342. $itemInfo = !empty($itemInfo['data'][0]) ? $itemInfo['data'][0] : [];
  343. $item['coupon_money'] = $itemInfo['coupon_money'] ?? 0;
  344. $item['coupon_url'] = !empty($itemInfo['coupon_url']) ? 'https:'.$itemInfo['coupon_url'] : '';
  345. $item['coupon_info'] = $itemInfo['coupon_info'] ?? '';
  346. $item['item_desc'] = $itemInfo['item_desc'] ?? '';
  347. $item['item_short_title'] = $itemInfo['item_short_title'] ?? '';
  348. $item['item_price'] = isset($item['zk_final_price']) ? $item['zk_final_price'] :
  349. (isset($item['item_price']) ? $item['item_price'] : 0);
  350. $item['item_end_price'] = (isset($item['coupon_money']) && $item['item_price'] > 0) ?
  351. $item['item_price'] - $item['coupon_money'] : $item['item_price'];
  352. # 获取商品淘口令
  353. $itemUrl = !empty($itemInfo['url']) ? $itemInfo['url'] :
  354. (!empty($itemInfo['coupon_url']) ? $itemInfo['coupon_url'] : '');
  355. $itemUrl = 'https:'.$itemUrl;
  356. $taoWordInfo = GoodsService::tpwdCreate($itemUrl);
  357. $item['taoword'] = $taoWordInfo['taoword'];
  358. $item['model'] = $taoWordInfo['model'];
  359. $data[] = $item;
  360. }
  361. if(1 == count($data)) {
  362. return $data[0];
  363. }
  364. return $data;
  365. }
  366. public static function sameGoods($itemId)
  367. {
  368. # 请求数据
  369. $res = HaoDanKuApi::get_similar_info($itemId);
  370. $promotionId = GoodsCommonService::getPromotionId();
  371. $data = [];
  372. if(isset($res['code']) && 1 == $res['code']) {
  373. $fieldMapping = HaoDanKuApi::fieldMapping();
  374. # 单独一个商品信息
  375. if (!empty($res['data'])) {
  376. foreach($res['data'] as $value) {
  377. $item = [];
  378. foreach($value as $k=>$v) {
  379. $newKey = $fieldMapping[$k] ?? null;
  380. if(!empty($newKey)) {
  381. $item[$newKey] = $v;
  382. }
  383. }
  384. $item['item_pic'] = !empty($item['item_pic']) ? $item['item_pic'].'_310x310.jpg' : '';
  385. $item['item_pic_copy'] = !empty($item['item_pic_copy']) ? 'http://img-haodanku-com.cdn.fudaiapp.com/'.$item['item_pic_copy'] : '';
  386. $item['promotion_id'] = $promotionId;
  387. $item['shop_type'] = GoodsCommonService::getShopType($item['shop_type'], 1);
  388. $data[] = $item;
  389. }
  390. }
  391. }
  392. return $data;
  393. }
  394. public static function createTaobaoWord($itemId, $promotionId, $itemTitle)
  395. {
  396. # 是否直接通过好单库接口获取淘口令
  397. $getTaobaoWord = false;
  398. if(!empty($itemTitle)) {
  399. if(mb_strlen($itemTitle) >= 8) {
  400. $getTaobaoWord = true;
  401. }
  402. }
  403. # 好单库转链
  404. $res = GoodsService::rateUrl($itemId, $promotionId, $getTaobaoWord, $itemTitle);
  405. # 如果好单库接口可以直接生成淘口令则直接返回
  406. if(!empty($res)) {
  407. if(!empty($res['taoword'])) {
  408. return [
  409. 'taoword' => $res['taoword'],
  410. 'model' => $res['new_model'],
  411. ];
  412. } else {
  413. $itemUrl = !empty($res['item_url']) ? $res['item_url'] :
  414. (!empty($res['coupon_click_url']) ? $res['coupon_click_url'] : '');
  415. }
  416. }
  417. if(empty($itemUrl)) {
  418. # 淘宝搜索接口获取链接
  419. $keyword = GoodsCommonService::getTaobaoUrl($itemId);
  420. $itemInfo = GoodsService::materialSearch(null, 1, $keyword, null, 1, null, 1, $promotionId);
  421. $itemInfo = !empty($itemInfo['data'][0]) ? $itemInfo['data'][0] : [];
  422. $itemUrl = !empty($itemInfo['url']) ? $itemInfo['url'] :
  423. (isset($itemInfo['coupon_share_url']) && !empty($itemInfo['coupon_share_url'] ? $itemInfo['coupon_share_url'] : ''));
  424. $itemUrl = 'https:'.$itemUrl;
  425. }
  426. $response = GoodsService::tpwdCreate($itemUrl);
  427. return $response;
  428. }
  429. public static function rateUrl($itemId, $promotionId, $getTaobaoWord, $itemTitle)
  430. {
  431. $tbName = config('haodanku.tb_name');
  432. $response = HaoDanKuApi::ratesurl($itemId, null, $promotionId, null, null, null, $tbName
  433. ,null, null, null, $getTaobaoWord, $itemTitle);
  434. if(isset($response['code']) && 1 == $response['code']) {
  435. # 请求成功
  436. return $response['data'];
  437. }
  438. return [];
  439. }
  440. public static function tpwdCreate($itemUrl)
  441. {
  442. if(empty($itemUrl)){
  443. return [
  444. 'taoword' => null,
  445. 'model' => null,
  446. ];
  447. }
  448. $method = 'taobao.tbk.tpwd.create';
  449. $paramsArr['url'] = $itemUrl;
  450. $res = TaoBaoApi::createRequest($method, $paramsArr);
  451. $data = $res['tbk_tpwd_create_response']['data'] ?? [];
  452. return [
  453. 'taoword' => $data['password_simple'] ?? null,
  454. 'model' => $data['model'] ?? null,
  455. ];
  456. }
  457. }