GoodsService.php 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651
  1. <?php
  2. namespace addons\WechatVideoShop\common\service;
  3. use addons\WechatVideoShop\common\enums\WechatVideoShopEnums;
  4. use addons\WechatVideoShop\common\enums\WechatVideoShopGoodsAuditStatusEnums;
  5. use addons\WechatVideoShop\common\enums\WechatVideoShopGoodsListingStatusEnums;
  6. use addons\WechatVideoShop\common\expand\sdk\weixin\src\model\basic\UploadImageModel;
  7. use addons\WechatVideoShop\common\expand\sdk\weixin\src\model\basic\UploadQualificationModel;
  8. use addons\WechatVideoShop\common\expand\sdk\weixin\src\model\goods\CatModel;
  9. use addons\WechatVideoShop\common\expand\sdk\weixin\src\model\goods\DescInfoModel;
  10. use addons\WechatVideoShop\common\expand\sdk\weixin\src\model\goods\ExpressInfoModel;
  11. use addons\WechatVideoShop\common\expand\sdk\weixin\src\model\goods\GoodsDeleteModel;
  12. use addons\WechatVideoShop\common\expand\sdk\weixin\src\model\goods\GoodsExtraServiceModel;
  13. use addons\WechatVideoShop\common\expand\sdk\weixin\src\model\goods\GoodsItem;
  14. use addons\WechatVideoShop\common\expand\sdk\weixin\src\model\goods\GoodsModel;
  15. use addons\WechatVideoShop\common\expand\sdk\weixin\src\model\goods\LimitedInfoModel;
  16. use addons\WechatVideoShop\common\expand\sdk\weixin\src\model\goods\SkuAttrItemModel;
  17. use addons\WechatVideoShop\common\expand\sdk\weixin\src\model\goods\SkuDeliverInfoModel;
  18. use addons\WechatVideoShop\common\expand\sdk\weixin\src\model\goods\SkuItemModel;
  19. use addons\WechatVideoShop\common\expand\sdk\weixin\src\model\goods\UpdateStockModel;
  20. use addons\WechatVideoShop\common\expand\sdk\weixin\src\request\basic\UploadImageRequest;
  21. use addons\WechatVideoShop\common\expand\sdk\weixin\src\request\basic\UploadQualificationRequest;
  22. use addons\WechatVideoShop\common\expand\sdk\weixin\src\request\goods\GoodsAddRequest;
  23. use addons\WechatVideoShop\common\expand\sdk\weixin\src\request\goods\GoodsAuditCancelRequest;
  24. use addons\WechatVideoShop\common\expand\sdk\weixin\src\request\goods\GoodsDeleteRequest;
  25. use addons\WechatVideoShop\common\expand\sdk\weixin\src\request\goods\GoodsDelistingRequest;
  26. use addons\WechatVideoShop\common\expand\sdk\weixin\src\request\goods\GoodsItemRequest;
  27. use addons\WechatVideoShop\common\expand\sdk\weixin\src\request\goods\GoodsListingRequest;
  28. use addons\WechatVideoShop\common\expand\sdk\weixin\src\request\goods\GoodsUpdateRequest;
  29. use addons\WechatVideoShop\common\expand\sdk\weixin\src\request\goods\GoodsUpdateStockRequest;
  30. use addons\WechatVideoShop\common\helper\WechatRequestHelper;
  31. use addons\WechatVideoShop\common\models\WechatVideoShop;
  32. use addons\WechatVideoShop\common\models\WechatVideoShopCate;
  33. use addons\WechatVideoShop\common\models\WechatVideoShopExpressTemplate;
  34. use addons\WechatVideoShop\common\models\WechatVideoShopGoods;
  35. use common\enums\StatusEnum;
  36. use common\models\goods\Goods;
  37. use common\models\goods\GoodsAttr;
  38. use common\traits\ErrorTrait;
  39. use yii\helpers\Json;
  40. class GoodsService
  41. {
  42. use ErrorTrait;
  43. public function push(int $mall_id, array $params, array $config)
  44. {
  45. try {
  46. $goods = Goods::getOne([
  47. ['mall_id' => $mall_id],
  48. ['id' => $params['goods_id']],
  49. ['status' => StatusEnum::ENABLED]
  50. ], true, ['attr', 'extra', 'collect']);
  51. if (empty($goods)) throw new \Exception('商品不存在');
  52. $goodsModel = new GoodsModel();
  53. $goodsModel->setAfterSaleAddressId(1);
  54. $goodsModel->after_sale_info['after_sale_address_id'] = 1;
  55. $goodsModel->title = mb_substr($goods['goods_name'], 0, 60);
  56. $goodsModel->sub_title = !empty($goods['subtitle']) ? mb_substr($goods['subtitle'], 0, 18) : '';
  57. $banner_images = Json::decode($goods['bannar_pic']);
  58. $banner_images = array_column($banner_images, 'pic_url');
  59. array_unshift($banner_images, $goods['cover_pic']);
  60. // 发货方式,若为无需快递(仅对部分类目开放),则无需填写运费模版id。0:快递发货(默认),1:无需快递
  61. // 需要将图片传至微信
  62. $req_banner_images = [];
  63. foreach ($banner_images as $banner_image) {
  64. $img_url = $this->uploadImage($banner_image, $config);
  65. if (!empty($img_url)) $req_banner_images[] = $img_url;
  66. }
  67. $goodsModel->head_imgs = $req_banner_images;
  68. // 0快递发货, 1无需物流
  69. $goodsModel->deliver_method = $goods['freight_type'] == StatusEnum::ENABLED || !empty($goods['shipping_fee']) ?
  70. StatusEnum::DISABLED : StatusEnum::ENABLED;
  71. // 详情 - 需要将图片拿出来
  72. // 文本也需要取出来
  73. if (empty($goods['detail'])) {
  74. throw new \Exception("商品详情不能为空");
  75. }
  76. $goodsModel->desc_info = $this->getDescInfo($goods['detail'], $config);
  77. // 类目
  78. $goodsModel->cats = $this->getCats($params['cat_id']);
  79. // 属性
  80. // https://developers.weixin.qq.com/doc/channels/API/product/add.html
  81. // 商品参数,部分类目有必填的参数,具体参考文档获取类目信息中的字段attr.product_attr_list[].is_required
  82. if (!empty($params['attrs'])) {
  83. $goodsModel->attrs = $this->getAttrs($params['attrs']);
  84. }
  85. // 品牌id,无品牌为“2100000000”
  86. if (!empty($params['brand_id'])) {
  87. $goodsModel->brand_id = $params['brand_id'];
  88. }
  89. // 产品ID
  90. if (!empty($params['product_id'])) {
  91. $goodsModel->product_id = $params['product_id'];
  92. }
  93. // 运费模板
  94. if ($goodsModel->deliver_method == StatusEnum::DISABLED) {
  95. $goodsModel->express_info = $this->getExpressTemplate($goods, $config, $params['shop_id']);
  96. }
  97. // 商品资质图片(最多5张)
  98. if (!empty($params['qualifications'])) {
  99. $goodsModel->qualifications = $params['qualifications'];
  100. }
  101. // 限购
  102. if ($goods['buy_num_limit'] > 0) {
  103. $limitedInfo = new LimitedInfoModel();
  104. $limitedInfo->limited_buy_num = $goods['buy_num_limit'];
  105. // 限购周期类型,0:无限购(默认),1:按自然日限购,2:按自然周限购,3:按自然月限购,4:按自然年限购
  106. $limitedInfo->period_type = 3; // 按年限购
  107. $goodsModel->limited_info = $limitedInfo;
  108. }
  109. // 售后
  110. $extraServiceModel = new GoodsExtraServiceModel();
  111. // 是否支持七天无理由退货,0-不支持七天无理由, 1-支持七天无理由, 2-支持七天无理由(定制商品除外)。
  112. //管理规则请参见七天无理由退货管理规则。类目是否必须支持七天无理由退货,可参考文档获取类目信息中的字段attr.seven_day_return
  113. $extraServiceModel->seven_day_return = $params['seven_day_return'] == StatusEnum::ENABLED ? StatusEnum::ENABLED : StatusEnum::DISABLED;
  114. $goodsModel->extra_service = $extraServiceModel;
  115. // 最少要一个
  116. if (!empty($goods['attr'])) {
  117. $goodsModel->skus = $this->getSkus($goods, $config);
  118. }
  119. // 判断是否有产品ID,有的话则为更新商品
  120. if (!empty($params['product_id'])) {
  121. $req = new GoodsUpdateRequest($config);
  122. } else {
  123. $req = new GoodsAddRequest($config);
  124. }
  125. $resp = WechatRequestHelper::accessTokenAndToArray($req, $goodsModel);
  126. if (!empty($resp['data']['product_id'])) { // 判断是否为编辑
  127. $model = WechatVideoShopGoods::getOne([
  128. ['product_id' => $params['product_id']]
  129. ]);
  130. if (empty($model)) {
  131. $model = new WechatVideoShopGoods();
  132. }
  133. $model->mall_id = $goods['mall_id'];
  134. $model->goods_id = $goods['id'];
  135. $model->shop_id = $params['shop_id'];
  136. $model->product_id = $resp['data']['product_id'];
  137. $model->audit_status = StatusEnum::DISABLED;
  138. // $model->audit_reason = '';
  139. $model->cate_ids = [
  140. $goodsModel->cats[0]->cat_id,
  141. $goodsModel->cats[1]->cat_id,
  142. $goodsModel->cats[2]->cat_id,
  143. ];
  144. $model->content = $goodsModel->toArray();
  145. $model->attrs = $params['attrs'] ?? [];
  146. if (!$model->save()) throw new \Exception($model->getErrorMessage());
  147. }
  148. return true;
  149. } catch (\Exception $e) {
  150. return $e->getMessage();
  151. }
  152. }
  153. /**
  154. * @param int $cat_id
  155. * @return array
  156. * @throws \Exception
  157. */
  158. protected function getCats(int $cat_id)
  159. {
  160. $cat = WechatVideoShopCate::getOne([
  161. ['id' => $cat_id]
  162. ], true, ['parent' => function ($query) {
  163. $query->with('parent');
  164. }]);
  165. if (empty($cat)) throw new \Exception("类目不存在");
  166. if (empty($cat['parent'])) throw new \Exception("上级类目不存在");
  167. if (empty($cat['parent']['parent'])) throw new \Exception("顶级类目不存在");
  168. $cats = [];
  169. $cat1Model = new CatModel();
  170. $cat1Model->cat_id = $cat['parent']['parent']['id'];
  171. $cats[] = $cat1Model;
  172. $cat2Model = new CatModel();
  173. $cat2Model->cat_id = $cat['parent']['id'];
  174. $cats[] = $cat2Model;
  175. $cat3Model = new CatModel();
  176. $cat3Model->cat_id = $cat['id'];
  177. $cats[] = $cat3Model;
  178. return $cats;
  179. }
  180. /**
  181. * @param string $content
  182. * @param array $config
  183. * @return DescInfoModel
  184. * @throws \Exception
  185. */
  186. protected function getDescInfo(string $content, array $config)
  187. {
  188. $text = strip_tags($content);
  189. $text = html_entity_decode($text, ENT_HTML5, "UTF-8");
  190. $text = mb_substr($text, 0, strlen($text), "UTF-8");
  191. $descInfoModel = new DescInfoModel();
  192. $descInfoModel->desc = $text;
  193. preg_match_all('/<img.*?src=[\'|\"](.*?)[\'|\"].*?[\/]?>/i', $content, $images);
  194. $pics = $images[1] ?? [];
  195. $req_banner_images = [];
  196. if (!empty($pics)) {
  197. foreach ($pics as $banner_image) {
  198. $img_url = $this->uploadImage($banner_image, $config);
  199. if (!empty($img_url)) $req_banner_images[] = $img_url;
  200. }
  201. }
  202. $descInfoModel->imgs = $req_banner_images;
  203. return $descInfoModel;
  204. }
  205. /**
  206. * @param array $goods
  207. * @param array $config
  208. * @param int $shop_id
  209. * @return ExpressInfoModel
  210. * @throws \Exception
  211. */
  212. protected function getExpressTemplate(array $goods, array $config, int $shop_id)
  213. {
  214. $model = new ExpressInfoModel();
  215. // 运费规则 【1运费模板 2自定义运费】
  216. $is_free = StatusEnum::DISABLED;
  217. // 如果运费模板ID为0的时候 那么证明就是自定义运费了
  218. if ($goods['freight_rules_type'] == StatusEnum::ENABLED && $goods['freight_id'] > 0) { // 运费模板方式
  219. // 运费模板ID
  220. // 取出运费模板ID
  221. $model->template_id = WechatVideoShopExpressTemplate::find()
  222. ->where(['mall_id' => $goods['mall_id']])
  223. ->andWhere(['shop_id' => $shop_id])
  224. ->andWhere(['template_id' => $goods['freight_id']])
  225. ->andWhere(['status' => StatusEnum::ENABLED])
  226. ->select('third_template_id')->scalar();
  227. } else { // 自定义运费
  228. if ($goods['shipping_fee'] == 0) { // 包邮
  229. // 取出包邮ID
  230. $model->template_id = WechatVideoShopExpressTemplate::find()
  231. ->where(['mall_id' => $goods['mall_id']])
  232. ->andWhere(['shop_id' => $shop_id])
  233. ->andWhere(['is_free' => StatusEnum::ENABLED])
  234. ->andWhere(['status' => StatusEnum::ENABLED])
  235. ->select('third_template_id')->scalar();
  236. if (empty($model->template_id)) {
  237. // 需要创建一个包邮模板
  238. $is_free = StatusEnum::ENABLED;
  239. }
  240. }
  241. if (empty($model->template_id)) { // 通过商品ID能否找出来
  242. $model->template_id = WechatVideoShopExpressTemplate::find()
  243. ->where(['mall_id' => $goods['mall_id']])
  244. ->andWhere(['shop_id' => $shop_id])
  245. ->andWhere(['goods_id' => $goods['id']])
  246. ->andWhere(['status' => StatusEnum::ENABLED])
  247. ->select('third_template_id')->scalar();
  248. }
  249. }
  250. if (empty($model->template_id)) {
  251. if ($is_free == StatusEnum::DISABLED && $goods['price'] < 30) {
  252. throw new \Exception("售价小于30的商品必须包邮");
  253. }
  254. // 需要创建
  255. $expressService = new ExpressTemplateService();
  256. $ret = $expressService->create($goods['mall_id'], $is_free, $goods, $config, $shop_id);
  257. if (is_string($ret)) throw new \Exception($ret);
  258. $model->template_id = $ret->third_template_id;
  259. }
  260. // 重量?
  261. $model->weight = GoodsAttr::find()
  262. ->andWhere(['goods_id' => $goods['id']])
  263. ->andWhere(['status' => StatusEnum::ENABLED])
  264. ->orderBy('weight desc')
  265. ->select('weight')->scalar();
  266. if (empty($model->weight)) $model->weight = 10; // 默认10克
  267. $model->weight = (int) $model->weight;
  268. return $model;
  269. }
  270. /**
  271. * @param array $data
  272. * @return array
  273. */
  274. protected function getAttrs(array $data)
  275. {
  276. $attrs = [];
  277. foreach ($data as $key => $value) {
  278. $attrItemModel = new SkuAttrItemModel();
  279. $attrItemModel->attr_key = $key;
  280. $attrItemModel->attr_value = $value;
  281. $attrs[] = $attrItemModel;
  282. }
  283. return $attrs;
  284. }
  285. /**
  286. * @param array $goods
  287. * @param array $config
  288. * @return array
  289. * @throws \Exception
  290. */
  291. protected function getSkus(array $goods, array $config)
  292. {
  293. $skus = [];
  294. foreach ($goods['attr'] as $sku) {
  295. $skuModel = new SkuItemModel();
  296. $skuModel->out_sku_id = $sku['id'];
  297. if (!empty($sku['pic_url'])) {
  298. $sku['pic_url'] = $this->uploadImage($sku['pic_url'], $config);
  299. }
  300. $skuModel->thumb_img = $sku['pic_url'];
  301. $skuModel->sku_code = $sku['goods_no'];
  302. $skuModel->sale_price = (float)bcmul($sku['price'], 100); // 售卖价格,以分为单位,不超过1000000000(1000万元)
  303. $skuModel->stock_num = (int)$sku['stock'];
  304. $skuDeliverInfoModel = new SkuDeliverInfoModel();
  305. $skuDeliverInfoModel->stock_type = StatusEnum::DISABLED; // 0现货,1预售
  306. $skuModel->sku_deliver_info = $skuDeliverInfoModel;
  307. // 颜色:绿色,尺码:小
  308. $sku_attrs = [];
  309. if (empty($sku['name'])) {
  310. $skuAttrItemModel = new SkuAttrItemModel();
  311. $skuAttrItemModel->attr_key = '选择规格';
  312. $skuAttrItemModel->attr_value = '默认规格';
  313. $sku_attrs[] = $skuAttrItemModel;
  314. } else {
  315. $names = explode(",", $sku['name']);
  316. foreach ($names as $name) {
  317. $name_arr = explode(":", $name);
  318. $skuAttrItemModel = new SkuAttrItemModel();
  319. $skuAttrItemModel->attr_key = "{$name_arr[0]}";
  320. $skuAttrItemModel->attr_value = $name_arr[1];
  321. $sku_attrs[] = $skuAttrItemModel;
  322. }
  323. }
  324. $skuModel->sku_attrs = $sku_attrs;
  325. $skus[] = $skuModel;
  326. }
  327. return $skus;
  328. }
  329. protected function parseCateAttrs(int $cat_id)
  330. {
  331. }
  332. public function getGoodsList($mall_id, $param)
  333. {
  334. try {
  335. $params['where'] = [
  336. ['mall_id' => $mall_id],
  337. ['status' => [StatusEnum::DISABLED, StatusEnum::ENABLED]]
  338. ];
  339. if(!empty($param['audit_status'])){
  340. $params['where'][] = ['audit_status' => $param['audit_status']];
  341. }
  342. if(!empty($param['shop_id'])){
  343. $params['where'][] = ['shop_id' => $param['shop_id']];
  344. }
  345. if (!empty($param['keyword'])) {
  346. $gids = Goods::find()->where(['mall_id' => $mall_id])
  347. ->andWhere(['status' => [StatusEnum::ENABLED, StatusEnum::DISABLED]])
  348. ->andWhere(['like', 'goods_name', $param['keyword']])
  349. ->select('id')->column();
  350. if (empty($gids)) return [];
  351. $params['where'][] = ['goods_id' => $gids];
  352. }
  353. $params['limit'] = $param['limit'] ?? 5;
  354. $params['page'] = $param['page'] ?? 1;
  355. $params['with'] = ['shop', 'goods'];
  356. $params['order'] = 'id desc';
  357. $list = WechatVideoShopGoods::listPage($params);
  358. if ($list === false) throw new \Exception(WechatVideoShopGoods::getStaticError());
  359. $audit_status = WechatVideoShopGoodsAuditStatusEnums::AUDIT_STATUS_REMARKS;
  360. $listing_status = WechatVideoShopGoodsListingStatusEnums::AUDIT_STATUS_REMARKS;
  361. $shop_list = WechatVideoShop::lists([
  362. 'where' => [
  363. ['mall_id' => $mall_id],
  364. ],
  365. 'index' => 'id'
  366. ]);
  367. foreach ($list['list'] as &$val) {
  368. $val['audit_text'] = $audit_status[$val['audit_status']] ?? '未知状态';
  369. $val['listing_text'] = $listing_status[$val['listing_status']] ?? '未知状态';
  370. $itemModel = new GoodsItem();
  371. $itemModel->product_id = $val['product_id'];
  372. $itemModel->data_type = 3;
  373. $val['third_data'] = WechatRequestHelper::accessTokenAndToArray(new GoodsItemRequest($shop_list[$val['shop_id']]), $itemModel);
  374. $val['stock'] = !empty($val['third_data']['edit_product']['skus']) ?
  375. array_sum(array_column($val['third_data']['edit_product']['skus'], 'stock_num')) : 0;
  376. if (!empty($val['third_data']['product']['skus'])) {
  377. $val['stock'] = array_sum(array_column($val['third_data']['product']['skus'], 'stock_num'));
  378. }
  379. }
  380. unset($val);
  381. return $list;
  382. } catch (\Exception $e) {
  383. $this->setError($e->getMessage());
  384. return false;
  385. }
  386. }
  387. /**
  388. * 创建商品
  389. * @param int $mall_id
  390. * @param array $data
  391. * @return string|true
  392. * @throws \Exception
  393. */
  394. public function create(int $mall_id, array $data)
  395. {
  396. $qualifications = [];
  397. $config = (new ShopService())->getShop($data['shop_id']);
  398. if (!empty($data['qualifications'])) {
  399. foreach ($data['qualifications'] as $param) {
  400. if (strpos($param, 'https://mmecimage.cn/') === 0) {
  401. $qualifications[] = $param;
  402. } else {
  403. // 如果没有文件格式,那么这里会报错,所以必须要一个文件格式?
  404. $pic_url = $this->uploadImage($param, $config);
  405. if (!empty($pic_url)) $qualifications[] = $pic_url;
  406. }
  407. }
  408. }
  409. $attr = !empty($data['attr']) ? $data['attr'] : [];
  410. $sale_attr = !empty($data['sale_attr']) ? $data['sale_attr'] : [];
  411. $tmp_attrs = array_merge($attr, $sale_attr);
  412. // 这里之前需要处理一下数据
  413. foreach ($tmp_attrs as &$t_attr) {
  414. switch ($t_attr['ext']['type_v2']) {
  415. case 'integer':
  416. $t_attr['value'] = intval(!empty($t_attr['value']) ? $t_attr['value'] : 0);
  417. break;
  418. case 'decimal4':
  419. $t_attr['value'] = bcmul(!empty($t_attr['value']) ? $t_attr['value'] : 0, 1, 4);
  420. break;
  421. case 'integer_unit':
  422. $t_attr['value'] = intval(!empty($t_attr['value']) ? $t_attr['value'] : 0) . " {$t_attr['ext']['value']}";
  423. break;
  424. case 'decimal4_unit':
  425. $t_attr['value'] = bcmul(!empty($t_attr['value']) ? $t_attr['value'] : 0, 1, 4) . " {$t_attr['ext']['value']}";
  426. break;
  427. case 'select_many':
  428. $t_attr['value'] = !empty($t_attr['value']) && is_array($t_attr['value']) ? implode(";", $t_attr['value']) : '';
  429. break;
  430. }
  431. }
  432. $attrs = array_combine(array_column($tmp_attrs, "name"), array_column($tmp_attrs, "value"));
  433. $attrs = array_filter($attrs, function ($val) {
  434. return !empty($val);
  435. });
  436. // 创建商品
  437. return $this->push($mall_id, [
  438. 'goods_id' => $data['goods_id'],
  439. 'attrs' => $attrs,
  440. 'cat_id' => $data['cat_id'],
  441. 'shop_id' => $data['shop_id'],
  442. 'seven_day_return' => $data['seven_day_return'],
  443. 'qualifications' => $qualifications, // 资质上传
  444. // 'brand_id' => ''
  445. 'product_id'=> $data['product_id'] ?? ''
  446. ], $config);
  447. }
  448. /**
  449. * 上传图片
  450. * @param string $url
  451. * @param array $config
  452. * @return mixed|string
  453. * @throws \Exception
  454. */
  455. protected function uploadImage(string $url, array $config)
  456. {
  457. if (empty($url)) return '';
  458. $notPregUrl = '/(?<!:)\/+/';
  459. if (substr_count($url, '//') >= 2) {
  460. $url = preg_replace($notPregUrl, '/', $url);
  461. }
  462. $uploadModel = new UploadImageModel();
  463. // 如果图片地址没有图片类型的话那么是传不成功的,需要给其设置一个格式,比如 .jpg、.png?
  464. if (empty(pathinfo($url, PATHINFO_EXTENSION))) {
  465. $url .= '.jpg';
  466. }
  467. $uploadModel->img_url = $url;
  468. $uploadRequest = new UploadImageRequest($config);
  469. $resp = WechatRequestHelper::accessTokenAndToArray($uploadRequest->withQuery([
  470. "upload_type" => StatusEnum::ENABLED,
  471. "resp_type" => StatusEnum::ENABLED,
  472. ]), $uploadModel);
  473. return $resp['pic_file']['img_url'] ?? '';
  474. }
  475. /**
  476. * @param int $mall_id
  477. * @param int $id
  478. * @return string|true
  479. */
  480. public function delete(int $mall_id, int $id)
  481. {
  482. $goods = WechatVideoShopGoods::getOne([
  483. ['mall_id' => $mall_id],
  484. ['id' => $id],
  485. ]);
  486. if (empty($goods)) return '商品不存在';
  487. $config = (new ShopService())->getShop($goods->shop_id);
  488. $goodsModel = new GoodsDeleteModel();
  489. $goodsModel->product_id = $goods->product_id;
  490. try {
  491. WechatRequestHelper::accessTokenAndToArray(new GoodsDeleteRequest($config), $goodsModel);
  492. $goods->status = StatusEnum::DELETE;
  493. if (!$goods->save()) throw new \Exception($goods->getErrorMessage());
  494. } catch (\Exception $e) {
  495. return $e->getMessage();
  496. }
  497. return true;
  498. }
  499. /**
  500. * @param int $mall_id
  501. * @param int $id
  502. * @param int $type
  503. * @return string|true
  504. */
  505. public function onSale(int $mall_id, int $id, int $type)
  506. {
  507. $goods = WechatVideoShopGoods::getOne([
  508. ['mall_id' => $mall_id],
  509. ['id' => $id],
  510. ]);
  511. if (empty($goods)) return '商品不存在';
  512. $config = (new ShopService())->getShop($goods->shop_id);
  513. $goodsModel = new GoodsDeleteModel();
  514. $goodsModel->product_id = $goods->product_id;
  515. try {
  516. if ($type == StatusEnum::DISABLED) { // 下架
  517. $req = new GoodsDelistingRequest($config);
  518. } else {
  519. $req = new GoodsListingRequest($config);
  520. }
  521. WechatRequestHelper::accessTokenAndToArray($req, $goodsModel);
  522. } catch (\Exception $e) {
  523. return $e->getMessage();
  524. }
  525. return true;
  526. }
  527. /**
  528. * 取消审核
  529. * @param int $mall_id
  530. * @param int $id
  531. * @return string|true
  532. */
  533. public function cancelAudit(int $mall_id, int $id)
  534. {
  535. $goods = WechatVideoShopGoods::getOne([
  536. ['mall_id' => $mall_id],
  537. ['id' => $id],
  538. ]);
  539. if (empty($goods)) return '商品不存在';
  540. $config = (new ShopService())->getShop($goods->shop_id);
  541. $goodsModel = new GoodsDeleteModel();
  542. $goodsModel->product_id = $goods->product_id;
  543. try {
  544. WechatRequestHelper::accessTokenAndToArray(new GoodsAuditCancelRequest($config), $goodsModel);
  545. $goods->audit_status = StatusEnum::DISABLED;
  546. if (!$goods->save()) throw new \Exception($goods->getErrorMessage());
  547. } catch (\Exception $e) {
  548. return $e->getMessage();
  549. }
  550. return true;
  551. }
  552. /**
  553. * 更新库存
  554. * @param int $mall_id
  555. * @param int $id
  556. * @param array $skus
  557. * @return string|true
  558. */
  559. public function setStock(int $mall_id, int $id, array $skus)
  560. {
  561. $goods = WechatVideoShopGoods::getOne([
  562. ['mall_id' => $mall_id],
  563. ['id' => $id],
  564. ]);
  565. if (empty($goods)) return '商品不存在';
  566. $config = (new ShopService())->getShop($goods->shop_id);
  567. foreach ($skus as $sku) {
  568. if ($sku['num'] != $sku['stock_num']) {
  569. $stockModel = new UpdateStockModel();
  570. $stockModel->product_id = $goods->product_id;
  571. $stockModel->sku_id = $sku['sku_id'];
  572. $stockModel->diff_type = 3; // 修改类型。1: 增加;2:减少;3:设置。
  573. $stockModel->num = intval($sku['num']); // 增加、减少或者设置的库存值
  574. try {
  575. $resp = WechatRequestHelper::accessTokenAndToArray(new GoodsUpdateStockRequest($config), $stockModel);
  576. } catch (\Exception $e) {
  577. return $e->getMessage();
  578. }
  579. }
  580. }
  581. return true;
  582. }
  583. }