MsgGoodsPrice.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. <?php
  2. namespace app\console\Commands;
  3. use app\common\facades\EasyWeChat;
  4. use app\common\facades\Setting;
  5. use app\common\models\AccountWechats;
  6. use app\common\models\goods\GoodsFiltering;
  7. use app\common\models\Member;
  8. use app\common\models\notice\MessageTemp;
  9. use app\common\models\TemplateMessageRecord;
  10. use app\common\services\MessageService;
  11. use app\platform\modules\system\models\SystemSetting;
  12. use GuzzleHttp\Client;
  13. use Illuminate\Support\Arr;
  14. use Illuminate\Support\Facades\DB;
  15. use Yunshop\Commission\models\Commission;
  16. use Yunshop\Integral\Common\Models\IntegralGoodsModel;
  17. use Yunshop\YzSupply\models\Goods;
  18. use Illuminate\Console\Command;
  19. class MsgGoodsPrice extends Command
  20. {
  21. const HOST = 'http://110.42.254.179/OpenPlatForm/openapi';
  22. const ACCOUNT = 'gbcszh_adm';
  23. const ACTION = 'sendbatch';
  24. const FORMAT = 'json';
  25. const AUTH_KEY = 'e10adc3949ba59abbe56e057f20f883e';
  26. const AUTH_NAME = '【世纪汇杰】';
  27. protected $signature = 'msg:goodsPrice {--phone=13453837482}';
  28. protected $pageSize = 2000;
  29. /**
  30. * The console command description.
  31. *
  32. * @var string
  33. */
  34. protected $description = '商品价格异常,发送短信';
  35. /**
  36. * Execute the console command.
  37. *
  38. */
  39. /*public function handle()
  40. {
  41. $p = $this->option("phone");
  42. $templates = $this->makeMsgTemplate($this->getGoodsList());
  43. $query = [
  44. 'account' => self::ACCOUNT,
  45. 'p' => $p,
  46. 's' => time(),
  47. 'action' => self::ACTION,
  48. 'format' => self::FORMAT,
  49. 'authkey' => self::AUTH_KEY,
  50. ];
  51. $client = new Client();
  52. foreach ($templates as $template) {
  53. $query['c'] = self::AUTH_NAME . $template;
  54. $url = self::HOST . '?' . $this->build_query($query, "&");
  55. \Log::info($url);
  56. $client->get($url);
  57. }
  58. $this->output->success('发送短信成功');
  59. }*/
  60. public function handle(){
  61. $send_type=2;
  62. $p = $this->option("phone");
  63. $templates = $this->makeMsgTemplate($this->getGoodsList());
  64. if($send_type==1){
  65. if (!app('plugins')->isEnabled('elisoftsms')) {
  66. throw new \Exception('未开启验证码,请联系管理员!');
  67. }
  68. $setting = SystemSetting::settingLoad('sms', 'system_sms');
  69. $sms = ['elisoft_account'=>'hxn_adm',
  70. 'elisoft_password'=>'5404392e586ea34541c62db58694eb00',
  71. 'elisoft_signname'=>'【世纪汇杰】'];//Setting::get('shop.sms');
  72. $account = $sms['elisoft_account'];
  73. $passward = $sms['elisoft_password'];
  74. $signname=$sms['elisoft_signname'];
  75. if($setting['interior_sms_type']==1){
  76. $sms = new \Yunshop\Elisoftsms\services\ElisoftSmsService($account,$passward);
  77. foreach ($templates as $template) {
  78. $msg=$signname.$template;
  79. $param = [
  80. 'c' => urlencode($msg),
  81. 'p' => $p,
  82. ];
  83. $res = $sms->setAction('sendbatch')->send($param);
  84. if($res==null){
  85. throw new \Exception('请检查后台短信配置');
  86. }
  87. if ($res['result'] != 1) {
  88. throw new \Exception($res['errormsg']);
  89. }else{
  90. $this->output->success('发送短信成功');
  91. }
  92. }
  93. }else{
  94. $query = [
  95. 'uid'=>$setting['klws_account'],
  96. 'pw'=>md5($setting['klws_password'].date('YmdHis')),
  97. 'mb'=>$p,
  98. 'tm'=>date('YmdHis'),
  99. ];
  100. $url="http://3qdx.com:18002/send.do";
  101. $client = new Client();
  102. foreach ($templates as $template) {
  103. $query['ms'] = self::AUTH_NAME . $template;
  104. $url = $url . '?' . $this->build_query($query, "&");
  105. \Log::info($url);
  106. $client->get($url);
  107. }
  108. $this->output->success('发送短信成功');
  109. }
  110. }else{
  111. $params = [
  112. ['value' => '商品通知'],
  113. ['value'=>'2024-02-06 12:13:42'],
  114. ['value' => '紧急'],
  115. ];
  116. $temp=DB::table('yz_message_template')->where(['template_id'=>'B9273ptcxVk6hDSoj_Z9g7mb6t0Llr_QfR9JNjm9MTw'])->first();
  117. $templates = [];
  118. $temp_data=json_decode($temp['data'],true);
  119. foreach ($temp_data as $k=> $row) {
  120. $templates[$row['keywords']] = [
  121. 'value' => $params[$k]['value'],
  122. 'color' => $row['color']
  123. ];
  124. }
  125. dump($templates);exit;
  126. $app=$this->wxNoticeSend('q3s8oLEhl8agyTspBf8eJTGfFqW3OpKVxvyo_NuMQfI', $templates, [1270],'', 4);
  127. }
  128. }
  129. private static function replaceTemplate($str, $datas = array())
  130. {
  131. $str='';
  132. foreach ($datas as $row ) {
  133. $str = str_replace('[' . $row['name'] . ']', $row['value'], $str);
  134. }
  135. return $str;
  136. }
  137. /**
  138. * @param $data
  139. * @param string $separator
  140. * @return string
  141. */
  142. private function build_query($data, string $separator): string
  143. {
  144. $string = '';
  145. foreach ($data as $key => $item) {
  146. $string .= "{$key}={$item}" . $separator;
  147. }
  148. return rtrim($string, $separator) ;
  149. }
  150. private function getGoodsList(): array
  151. {
  152. $requestSearch = [];
  153. /*$list = Goods::Search($requestSearch)->with(['hasOneSmallCodeUrl', 'hasManyOptions', 'hasManyGoodsDiscount', 'hasOneYzGoods' => function ($query) {
  154. $query->with('hasOneMiddlegroundConfiguration');
  155. }])->pluginId()->orderBy('display_order', 'desc')->orderBy('yz_goods.id', 'desc');
  156. if (!empty($requestSearch['middleground_configuration_id'])) {
  157. $list = $list->whereHas('hasOneYzGoods', function ($query) use ($requestSearch) {
  158. $query->where('middleground_configuration_id', $requestSearch['middleground_configuration_id']);
  159. });
  160. }*/
  161. $list=DB::table('yz_goods')
  162. ->select('yz_goods.id','yz_goods.status','yz_goods.price','yz_goods.cost_price','yz_goods_option.id as goods_option_id','yz_goods_option.title as goods_option_title','yz_goods_option.product_price as goods_option_product_price','yz_goods_option.cost_price as goods_option_cost_price','yz_goods_option.market_price as goods_option_market_price',
  163. 'yz_community_marketing_goods.is_open as qtj_status','yz_community_marketing_goods.alone_rule','yz_community_marketing_goods.alone_rule_rate','yz_community_marketing_goods.cashier_rate',
  164. 'yz_goods_sale.max_point_deduct')
  165. ->leftJoin('yz_goods_option','yz_goods_option.goods_id','=','yz_goods.id')
  166. ->leftJoin('yz_community_marketing_goods','yz_community_marketing_goods.goods_id','=','yz_goods.id')
  167. ->leftJoin('yz_goods_sale','yz_goods_sale.goods_id','=','yz_goods.id')
  168. ->where(['yz_goods.status'=>1,'yz_goods.uniacid'=>4])
  169. ->whereNull('yz_goods.deleted_at');
  170. $result = [];
  171. while (($data = $list->paginate($this->pageSize)) && $data->currentPage() <= $data->lastPage()) {
  172. $result[] = $this->processData($data->items());
  173. $currentPage = $data->currentPage();
  174. request()->offsetSet('page', ++$currentPage);
  175. }
  176. return Arr::collapse($result);
  177. }
  178. /**
  179. * 处理数据
  180. * @param $data
  181. * @return array
  182. */
  183. private function processData($data): array
  184. {
  185. $alert = [];
  186. $deduction_set=0;
  187. $deduction_set_max='0';
  188. foreach ($data as $l) {
  189. $price=$l['goods_option_product_price']?$l['goods_option_product_price']:$l['price'];
  190. $cost_price=$l['goods_option_cost_price']?$l['goods_option_cost_price']:$l['cost_price'];
  191. $goods_discount=DB::table('yz_goods_discount')->select('discount_method','level_id','discount_value')->where(['goods_id'=>$l['id']])->get();
  192. $max_member_price='0';
  193. $integralData=IntegralGoodsModel::uniacid()->select('deduction_set','deduction_set_max')->where('goods_id',$l['id'])->first();
  194. if($integralData){
  195. $integralData=$integralData->toArray();
  196. if($integralData['deduction_set']==1){
  197. $deduction_set=$integralData['deduction_set'];
  198. $deduction_set_max=$integralData['deduction_set_max'];
  199. }else{
  200. $deduction_set=\Setting::get('integral.deduction_set');
  201. $deduction_set_max=\Setting::get('integral.deduction_set_max');
  202. }
  203. }
  204. foreach ($goods_discount as $v => $d){
  205. if($d['discount_value']){
  206. if($d['discount_method']==1){
  207. //$value=$d['discount_value'].'折';
  208. //$member_price=$price-($price*$d['discount_value']/10);
  209. $member_yh_price=$price-$price*$d['discount_value']/10;
  210. }elseif ($d['discount_method']==2){
  211. //$value=$d['discount_value'].'元';
  212. //$member_price=$price-$d['discount_value'];
  213. $member_yh_price=$d['discount_value'];
  214. }elseif ($d['discount_method']==3){
  215. //$value=$d['discount_value'].'%';
  216. //$member_price=$price-($cost_price*$d['discount_value']/100);
  217. $member_yh_price=$cost_price*$d['discount_value']/100;
  218. }
  219. if($max_member_price<$member_yh_price){
  220. $max_member_price=$member_yh_price;
  221. }
  222. /*$member_hyj_lr=$member_price-$cost_price;
  223. $member_hyj_lrl=round(($member_price-$cost_price)*100/$cost_price.'%',2);
  224. $arr[]=$level_name.':'.$value;
  225. $arr1[]=$level_name.":".$member_price.'元';
  226. $arr2[]=$level_name.":".$member_yh_price.'元';
  227. $arr3[]=$level_name.":".$member_hyj_lr.'元';
  228. $arr4[]=$level_name.":".$member_hyj_lrl.'%';*/
  229. }
  230. }
  231. $qyjyh=$price*$l['alone_rule_rate']/100;
  232. if (strpos($l['max_point_deduct'], '%') !== false) {
  233. $jfzgdkje=$price*$l['max_point_deduct']/100;
  234. }else{
  235. $jfzgdkje=$l['max_point_deduct'];
  236. }
  237. $commission_goods = Commission::getGoodsSet($l['id'])->toArray();
  238. $commission_goods_rule=unserialize($commission_goods['rule']);
  239. $commission_first_arr1=$commission_first_arr2=$commission_first_arr3=$commission_first_arr4=[];
  240. $commission_second_arr1=$commission_second_arr2=$commission_second_arr3=$commission_second_arr4=[];
  241. // $commission_third_arr1=$commission_third_arr2=$commission_third_arr3=$commission_third_arr4=[];
  242. $max_commission_first_price=$max_first_rate='0';
  243. $max_commission_second_price=$max_second_rate='0';
  244. foreach ($commission_goods_rule as $cc){
  245. // $levelName=$cc['levelName'];
  246. if($max_first_rate <$cc['first_level_rate']){
  247. $max_first_rate=$cc['first_level_rate'];
  248. }
  249. if($max_second_rate <$cc['second_level_rate']){
  250. $max_second_rate=$cc['first_level_rate'];
  251. }
  252. /*if(isset($cc['first_level_rate'])&&$cc['first_level_rate']>0){
  253. $first_level_rate=$cc['first_level_rate'];
  254. $commission_first_arr1[]=$levelName.':'.$first_level_rate.'%';
  255. $commission_first_arr2[]=$levelName.':'.$first_level_rate/100*$price.'元';
  256. $commission_first_arr3[]=$levelName.':'.($price-($first_level_rate/100*$price)-$cost_price).'元';
  257. $commission_first_arr4[]=$levelName.':'.round(($price-($first_level_rate/100*$cost_price)-$cost_price)/$cost_price,2).'%';
  258. }
  259. if(isset($cc['second_level_rate'])&&$cc['second_level_rate']>0){
  260. $second_level_rate=$cc['second_level_rate'];
  261. $commission_second_arr1[]=$levelName.':'.$second_level_rate.'%';
  262. $commission_second_arr2[]=$levelName.':'.$second_level_rate/100*$price.'元';
  263. $commission_second_arr3[]=$levelName.':'.($price-($second_level_rate/100*$price)-$cost_price).'元';
  264. $commission_second_arr4[]=$levelName.':'.round(($price-($second_level_rate/100*$cost_price)-$cost_price)/$cost_price,2).'%';
  265. }*/
  266. /* if(isset($cc['third_level_rate'])&&$cc['third_level_rate']>0){
  267. $third_level_rate=$cc['third_level_rate'];
  268. $commission_third_arr1[]=$levelName.':'.$third_level_rate.'%';
  269. $commission_third_arr2[]=$levelName.':'.$third_level_rate/100*$price.'元';
  270. $commission_third_arr3[]=$levelName.':'.($price-($third_level_rate/100*$price)-$cost_price).'元';
  271. $commission_third_arr4[]=$levelName.':'.round(($price-($third_level_rate/100*$cost_price)-$cost_price)/$cost_price,2).'%';
  272. }*/
  273. }
  274. $max_commission_first_price=$max_first_rate/100*$price;
  275. $max_commission_second_price=$max_second_rate/100*$price;
  276. $max_price_arr=[$max_member_price,$jfzgdkje];
  277. if($l['qtj_status']==1&&$l['alone_rule']==1){
  278. array_push($max_price_arr,$qyjyh);
  279. }
  280. if($deduction_set==1){
  281. array_push($max_price_arr,$price*$deduction_set_max/100);
  282. }
  283. if($commission_goods['is_commission']==1&& $commission_goods['has_commission']==1){
  284. array_push($max_price_arr,$max_commission_first_price,$max_commission_second_price);
  285. }
  286. $max_price=array_sum($max_price_arr);
  287. $record = [
  288. 'goods_id' => $l['id'],
  289. 'goods_option_id'=>$l['goods_option_id'],
  290. 'product_price' => $price,
  291. 'cost_price' => $cost_price,
  292. 'max_price'=>$max_price
  293. ];
  294. $sf_price=$price-$max_price;
  295. if ($record['product_price'] <= $record['cost_price']||$sf_price<=$record['cost_price']) {
  296. DB::table('yz_goods')->where('id',$record['goods_id'])->update(['status'=>0]);
  297. $alert[] = $record;
  298. }
  299. }
  300. return $alert;
  301. }
  302. /**
  303. * 生成短信模板
  304. * @param array $data
  305. * @return array
  306. */
  307. private function makeMsgTemplate(array $data): array
  308. {
  309. // $template = '商品id:1,现价:122,会员:100,VIP:82,成本:90,VIP会员利润报警';
  310. \Log::info($data);
  311. $templates = [];
  312. foreach (array_chunk($data, 4) as $chunk) {
  313. $template = '下架异常商品:';
  314. foreach ($chunk as $item) {
  315. if($item['goods_option_id']){
  316. $template .= sprintf('商品id:%d,商品规格id:%d,商品规格现价:%.2F,峰值金额:%.2f,商品规格成本:%.2f,利润报警|', $item['goods_id'],$item['goods_option_id'], $item['product_price'],$item['max_price'], $item['cost_price']);
  317. }else{
  318. $template .= sprintf('商品id:%d,商品现价:%.2F,峰值金额:%.2f,成本:%.2f,利润报警|', $item['goods_id'], $item['product_price'],$item['max_price'], $item['cost_price']);
  319. }
  320. }
  321. $templates[] = rtrim($template, "|");
  322. }
  323. return $templates;
  324. }
  325. private function wxNoticeSend($temp_id, array $params,array $member_ids, $url='', $uniacid='')
  326. {
  327. if ($uniacid) {
  328. \Setting::$uniqueAccountId = \YunShop::app()->uniacid = $uniacid;
  329. } else{
  330. \Setting::$uniqueAccountId = \YunShop::app()->uniacid;
  331. }
  332. foreach ($member_ids as $member_id){
  333. $member = Member::whereUid($member_id)->first();
  334. if (!isset($member)) {
  335. \Log::error("微信消息推送失败,未找到uid:{$member_id}的用户");
  336. return false;
  337. }
  338. if (!$member->isFollow()) {
  339. return false;
  340. }
  341. $accountWechat = AccountWechats::getAccountByUniacid(\YunShop::app()->uniacid);
  342. if (!isset($accountWechat)) {
  343. \Log::error("微信消息推送:未找到uniacid:{$uniacid}的配置信息");
  344. return false;
  345. }
  346. $config=['app_id' => $accountWechat->key, 'secret' => $accountWechat->secret];
  347. try {
  348. $app = EasyWeChat::officialAccount($config);
  349. $userService = $app->user;
  350. $user = $userService->get($member->hasOneFans->openid);
  351. if ($user['subscribe'] != 1 && $user->subscribe != 1) {
  352. \Log::debug('微信消息推送:用户未关注公众号',$user);
  353. return false;
  354. }
  355. $app->template_message->send([
  356. 'touser' => $member->hasOneFans->openid,
  357. 'template_id' => $temp_id,
  358. 'url' => $url,
  359. 'data' => $params,
  360. ]);
  361. } catch (Exception $error) {
  362. TemplateMessageRecord::create([
  363. 'uniacid' => \YunShop::app()->uniacid,
  364. 'member_id' => $member_id,
  365. 'template_id' => $temp_id,
  366. 'url' => $url?:'无',
  367. 'openid' => $member->hasOneFans->openid ?: 0,
  368. 'data' => json_encode($params),
  369. 'send_time' => time(),
  370. 'status' => -1,
  371. 'extend_data' => $error->getMessage(),
  372. ]);
  373. return true;
  374. }
  375. }
  376. }
  377. }