MallController.php 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  1. <?php
  2. namespace api\modules\v1\controllers;
  3. header('Access-Control-Allow-Origin:*');
  4. use addons\AiCustomerService\common\services\SettingService;
  5. use api\controllers\OnAuthController;
  6. use api\services\MallService;
  7. use common\enums\AddonsEnum;
  8. use common\enums\AppEnum;
  9. use common\enums\DiyEnum;
  10. use common\enums\RabbitMqEnum;
  11. use common\enums\StatusEnum;
  12. use common\events\mall\GetAdsCfgEvent;
  13. use common\helpers\sms\Sms;
  14. use common\helpers\map\QqMapHelper;
  15. use common\listeners\mall\BuyPointListener;
  16. use common\models\common\BuyingPointDay;
  17. use common\models\diy\DiyPage;
  18. use common\models\mall\MallAddons;
  19. use common\models\user\UserActionRecord;
  20. use common\models\user\UserPartitionRelationship;
  21. use Exception;
  22. use Yii;
  23. use yii\helpers\Json;
  24. use common\helpers\StringHelper;
  25. use common\models\common\AppVersion;
  26. /**
  27. * 商城控制器
  28. *
  29. *
  30. * Class MallController
  31. * @package frontend\controllers
  32. */
  33. class MallController extends OnAuthController
  34. {
  35. public $enableCsrfValidation = false;
  36. public $modelClass = '';
  37. /**
  38. * 不用进行登录验证的方法
  39. *
  40. * 例如: ['index', 'update', 'create', 'view', 'delete']
  41. * 默认全部需要验证
  42. *
  43. * @var array
  44. */
  45. protected $authOptional = ['config','get-img-base64','get-install-addons','sms-code','get-user-config','get-download-url','get-setting-value', 'check-app-version', 'reverse-geocoder', 'geocoder', 'get-near'];
  46. /**
  47. * 获取公共配置
  48. * @return mixed|void
  49. */
  50. public function actionConfig()
  51. {
  52. $request = Yii::$app->request;
  53. if ($request->isPost) {
  54. $mallId = $this->mall_id;
  55. // 获取底部导航栏
  56. $navbar = Yii::$app->services->setting->mall->get($mallId, 'bottom_nav');
  57. $navbar['navs'] = Json::decode($navbar['navs'],true);
  58. if ($navbar['navs']) {
  59. // 保证首页id实时性,获取装修首页ID
  60. $home_page_id = DiyPage::find()->select('id')->where(['mall_id'=>$mallId,'is_home_page'=>StatusEnum::ENABLED,'status'=>StatusEnum::ENABLED])->scalar();
  61. $navbar['navs'][0]['url'] = DiyPage::PAGE_PATH_DIY . '?id=' . $home_page_id;
  62. $navbar['navs'][0]['params']['route'] = DiyPage::PAGE_PATH_DIY . '?id=' . $home_page_id;
  63. //判断是否安装了门店管家
  64. $install = MallAddons::isInstall($mallId, AddonsEnum::ADDONS_NAME_STORE_STEWARD);
  65. if ($install) {
  66. $config = \Yii::$app->services->setting->addons->get($this->mall_id, AddonsEnum::ADDONS_NAME_STORE_STEWARD, 'basic');
  67. if ($config['index_type']) {
  68. $index_url = '/pages/AntTechnology/storeIndex/index';
  69. $navbar['navs'][0]['url'] = $index_url;
  70. $navbar['navs'][0]['params']['route'] = $index_url;
  71. }
  72. }
  73. }
  74. $data['navbar'] = $navbar;
  75. $data['service'] = Yii::$app->services->setting->mall->get($mallId, 'service');// 客服地址
  76. // 获取公共配置
  77. $basic = Yii::$app->services->setting->mall->get($mallId, 'basic');
  78. $data['basic'] = $basic;
  79. $data['share'] = ['share_title' => $basic['app_share_title'] ?? '', 'share_desc' => $basic['app_share_desc'] ?? '', 'share_pic' => $basic['app_share_pic'] ?? ''];
  80. $data['basic']['dollars_symbol'] = !empty($data['basic']['is_enable_dollars_symbol']) ? $data['basic']['dollars_symbol'] : '¥';
  81. // 获取用户配置
  82. $data['user_setting'] = Yii::$app->services->setting->mall->get($mallId, 'user');
  83. $data['user_setting']['allow_app_login'] = $data['user_setting']['allow_app_login'] ?: 1;// 默认开启APP登录
  84. // 获取版权配置
  85. $data['copyright'] = Yii::$app->services->setting->mall->get($mallId, 'copyright');
  86. // 获取sass平台的版权信息
  87. $system = Yii::$app->services->setting->platform->get('system');
  88. $data['copyright']['link_logo'] = $system['logo_url'] ?: '';
  89. $data['copyright']['link_text'] = $system['copyright'] ?: '';
  90. $data['copyright']['link_url'] = $system['copyright_url'] ?: '';
  91. $data['copyright']['link_status'] = $system['copyright_status'] ?: 0;
  92. $mall = $this->mall;
  93. if(empty($mall['is_show_copyright'])){
  94. $data['copyright']['link_status'] = 0;
  95. }
  96. $data['domain'] = [
  97. 'h5_url' => $system['h5_url'] ?: '',
  98. 'api_url' => $system['api_url'] ?: '',
  99. ];
  100. // 公共文字返回
  101. $data['global_text'] = [
  102. 'balance_name' => Yii::$app->services->setting->mall->get($mallId, 'balance.balance_name') ?? '余额',
  103. 'score_name' => Yii::$app->services->setting->mall->get($mallId, 'score.score_name') ?? '积分',
  104. ];
  105. // 用户设置
  106. $data['user_setting'] = Yii::$app->services->setting->mall->get($mallId, 'user');
  107. $data['user_setting']['check_sms_code'] = $data['user_setting']['check_sms_code'] ?? 1;// 默认开启验证码注册
  108. // 公众号设置
  109. $data['follow'] = Yii::$app->services->setting->mall->get($mallId, 'follow');
  110. $data['follow']['is_follw'] = 0;
  111. // 全局字体颜色
  112. $data['global_text_color'] = Yii::$app->services->setting->mall->get($mallId, 'decorate_setting.global_text_color');
  113. $data['global_goods_need'] = Yii::$app->services->setting->mall->get($mallId, 'decorate_setting.global_goods_need');
  114. $balance_pay_setting = Yii::$app->services->setting->mall->get($mallId, 'pay.balance');
  115. $balance_pay_setting = $balance_pay_setting ? json_decode($balance_pay_setting,'true') : [];
  116. $balance_pay_setting['is_setting_pay_password'] = 0;
  117. // 用户已登录
  118. if (!empty($this->user)) {
  119. if($this->user->transaction_password) $balance_pay_setting['is_setting_pay_password'] = 1;
  120. // 是否关注过公众号
  121. $follow = UserActionRecord::find()->select('follow')->where(['user_id' => $this->user_id])->scalar();
  122. $data['follow']['is_follw'] = $follow == 1 ? 1 : 0;
  123. }
  124. $data['balance_pay_setting'] = $balance_pay_setting;
  125. // 获取商城有效的插件
  126. $valid_addons = MallAddons::getValidAddons($this->mall_id);
  127. if (in_array('AiCustomerService', $valid_addons) && $this->user_id) {
  128. $data['ai_customer_service']['show_channel'] = (new SettingService(['mall_id' => $this->mall_id]))->getShowChannel();
  129. }
  130. if(in_array(AddonsEnum::ADDONS_NAME_STORE, $valid_addons)){
  131. $basic = \Yii::$app->services->setting->addons->get($this->mall_id, AddonsEnum::ADDONS_NAME_STORE, 'basic');
  132. $data['is_show_location_store'] = $basic['is_show_location_store'] ?? 0;
  133. $data['store']['is_enable_dollars_symbol'] = $basic['is_enable_dollars_symbol'];
  134. $data['store']['dollars_symbol'] = !empty($basic['is_enable_dollars_symbol']) ? $basic['dollars_symbol'] : '¥';
  135. }
  136. $data['valid_addons'] = $valid_addons;
  137. $relation_setting = \Yii::$app->services->setting->mall->get($mallId, 'user_relation_setting.relation_setting');
  138. if (!empty($relation_setting)) $relation_setting = json_decode($relation_setting, true);
  139. $data['become_child_way'] = $relation_setting['become_child_way']??1;
  140. $data['cat'] = Yii::$app->services->setting->mall->get($mallId, 'cat');
  141. $data['mall_name'] = $this->mall['name'];
  142. $data['pay_success_page'] = Yii::$app->services->setting->mall->get($this->mall_id,'order.pay_after_link');// 支付成功后跳转的地址
  143. $data['is_bind_popups'] = UserPartitionRelationship::getIsNeedPopups($this->mall_id, $this->user_id ?? 0);
  144. $order_nav_options = [
  145. ['name' => '商城订单', 'type' => 'default', 'url' => '/plugins/pages/order/list?tabIndex=0', 'open_type' => 'navigate']
  146. ];
  147. if(in_array(AddonsEnum::ADDONS_NAME_RESERVATION_SERVICE, $valid_addons) ||
  148. in_array(AddonsEnum::ADDONS_NAME_HOME_MAKING, $valid_addons)) $order_nav_options[] = ['name' => '服务订单', 'type' => AddonsEnum::ADDONS_NAME_HOME_MAKING, 'url' => '/plugins4/Housekeeping/service_order/list?tabIndex=0', 'open_type' => 'navigate'];
  149. if(in_array(AddonsEnum::ADDONS_NAME_BAI_MI_MOVIE, $valid_addons)) $order_nav_options[] = ['name' => '电影订单', 'type' => AddonsEnum::ADDONS_NAME_BAI_MI_MOVIE, 'url' => '/plugins2/Movie/order/list?tabIndex=0', 'open_type' => 'navigate'];
  150. if(in_array(AddonsEnum::ADDONS_NAME_CAKE, $valid_addons)) $order_nav_options[] = ['name' => '蛋糕订单', 'type' => AddonsEnum::ADDONS_NAME_CAKE, 'url' => '/plugins2/Cake/order/list?tabIndex=0', 'open_type' => 'navigate'];
  151. if(in_array(AddonsEnum::ADDONS_QIAN_XI_SUPPLY_CHAIN, $valid_addons)) $order_nav_options[] = ['name' => '权益商品订单', 'type' => AddonsEnum::ADDONS_QIAN_XI_SUPPLY_CHAIN, 'url' => '/plugins5/QianxiSupplyChain/orderList?tabIndex=0', 'open_type' => 'navigate'];
  152. if(in_array(AddonsEnum::ADDONS_SCORE_GAME, $valid_addons)) $order_nav_options[] = ['name' => '实体店订单', 'type' => AddonsEnum::ADDONS_SCORE_GAME, 'url' => '/customAddons/ScoreGame/physicalStore/orderList', 'open_type' => 'navigate'];
  153. if(in_array(AddonsEnum::ADDONS_NAME_LAO_DA_FU, $valid_addons)) {
  154. $order_nav_options[] = ['name' => '看诊订单', 'type' => AddonsEnum::ADDONS_NAME_LAO_DA_FU, 'url' => '/customDesigns/LaoDaFu/clientSide/visitOrderList', 'open_type' => 'navigate'];
  155. $order_nav_options[] = ['name' => '我的挂号', 'type' => AddonsEnum::ADDONS_NAME_LAO_DA_FU, 'url' => '/customDesigns/LaoDaFu/clientSide/registerOrderList', 'open_type' => 'navigate'];
  156. }
  157. // 获取插件配置
  158. $event = new GetAdsCfgEvent($this->mall_id);
  159. Yii::$app->services->events->dispatch($event, ['user' => $this->user]);
  160. $data['addons_config'] = $event->getConfig();
  161. // 订单设置
  162. $order_setting = Yii::$app->services->setting->mall->get($this->mall_id, 'order');
  163. $data['order'] = [
  164. 'is_show_positioning' => $order_setting['is_show_positioning'] ?? 1, // 显示定位按钮
  165. ];
  166. // 版本号
  167. $varsion = $request->post('version', 0);
  168. $varsion && $data['is_review'] = (new MallService(['mall_id' => $this->mall_id]))->getVersionReview($varsion);
  169. //获取总商城地图配置
  170. $map_setting = Yii::$app->services->setting->platform->get('map');
  171. $data['real_time_map'] = $map_setting['is_location'] ? $map_setting['is_location'] : 0;
  172. $data['order_nav_options'] = $order_nav_options;
  173. // 登录时是否填写昵称
  174. $data['basic']['is_write_name'] = !isset($data['basic']['is_write_name']) ? 0 : $data['basic']['is_write_name'];
  175. $this->success('获取成功', $data);
  176. }
  177. }
  178. /**
  179. * 获取图片base64数据接口
  180. * @Author: lun
  181. * @DateTime: 2021/11/12 0012 14:07
  182. * @Copyright: copyright (c) 2021 广东七件事集团
  183. */
  184. public function actionGetImgBase64()
  185. {
  186. $url = Yii::$app->request->get('url','');
  187. // $this->redirect($url);
  188. if(!empty($url)){
  189. $option=array('ssl'=>array('verify_peer' => false,'verify_peer_name' => false));
  190. $image = file_get_contents($url,false,stream_context_create($option));
  191. header('Content-type: image/jpg');
  192. echo $image;
  193. exit;
  194. }
  195. }
  196. /**
  197. * 用户买点接口
  198. * @Author: lun
  199. * @DateTime: 2021/11/30 0030 14:20
  200. * @Copyright: copyright (c) 2021 广东七件事集团
  201. * @return mixed|void
  202. */
  203. public function actionBuyingPoint()
  204. {
  205. $retuest = Yii::$app->request;
  206. if ($retuest->isPost) {
  207. try {
  208. $params = Yii::$app->request->post('form');
  209. $data = [
  210. 'mall_id' => $this->mall_id,
  211. 'user_id' => $this->user_id,
  212. 'card_id' => $this->card_id,
  213. 'list' => $params,
  214. ];
  215. Yii::$app->services->rabbitMq->push(RabbitMqEnum::EXCHANGE_TASK, RabbitMqEnum::TASK_QUEUE, $data, BuyPointListener::class, 'async_handle');
  216. $this->success('保存成功');
  217. } catch (\Exception $e) {
  218. $this->error('买点保存失败,mag=' . $e->getMessage());
  219. }
  220. }
  221. }
  222. /**
  223. * 发送验证码-公共方法
  224. * @Author: lun
  225. * @DateTime: 2023/5/12 0012 17:27
  226. * @Copyright: copyright (c) 2021 广东七件事集团
  227. * @return mixed|void
  228. * @throws \Overtrue\EasySms\Exceptions\NoGatewayAvailableException
  229. */
  230. public function actionSmsCode()
  231. {
  232. $retuest = Yii::$app->request;
  233. if ($retuest->isPost) {
  234. $params = $retuest->post();
  235. $res = Yii::$app->services->validate->validate($params, [
  236. [['mobile'], 'required', 'message' => '请输入手机号码'],
  237. [['mobile','area_code'], 'integer'],
  238. [['sms_type'], 'string'],
  239. ]);
  240. if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  241. $area_code = '';// 初始化区号
  242. $gateways = 'domestic';// 默认国内短信
  243. // 检测是登录并且区号不为空则使用国际短信
  244. if (!empty($this->user) && !empty($this->user->area_code)) {
  245. if ($this->user->area_code != 86) $gateways = 'international';
  246. $area_code = $this->user->area_code;
  247. }
  248. // 判断是否有区号
  249. if (!empty($params['area_code']) && $params['area_code'] != 86) {
  250. $gateways = 'international';
  251. $area_code = $params['area_code'];
  252. }
  253. $params['sms_type'] = $params['sms_type'] ?: '';
  254. $sms = new Sms($this->mall_id, $gateways);
  255. try {
  256. if ($sms->sendCaptcha($params['mobile'], $area_code,$params['sms_type']) === false) return $this->error('发送失败');
  257. }catch (Exception $e){
  258. return $this->error($e->getMessage());
  259. }
  260. return $this->success('发送成功');
  261. }
  262. }
  263. /**
  264. * 验证码校验
  265. *
  266. * @return void
  267. */
  268. public function actionCheckSmsCode()
  269. {
  270. $retuest = Yii::$app->request;
  271. if ($retuest->isPost) {
  272. $params = $retuest->post();
  273. $res = Yii::$app->services->validate->validate($params, [
  274. [['mobile'], 'required', 'message' => '请输入手机号码'],
  275. [['code'], 'required', 'message' => '请输入验证码'],
  276. [['mobile', 'area_code'], 'integer'],
  277. [['sms_type', 'code'], 'string'],
  278. ]);
  279. if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  280. $gateways = 'domestic';// 默认国内短信
  281. // 检测是登录并且区号不为空则使用国际短信
  282. if (!empty($this->user) && !empty($this->user->area_code)) {
  283. if ($this->user->area_code != 86) $gateways = 'international';
  284. }
  285. // 判断是否有区号
  286. if (!empty($params['area_code']) && $params['area_code'] != 86) {
  287. $gateways = 'international';
  288. }
  289. $code = $params['code'];
  290. $sms = new Sms($this->mall_id, $gateways);
  291. try {
  292. if ($sms->checkValidateCode($params['mobile'], $code, $params['sms_type']) === false) return $this->error('验证失败');
  293. return $this->success('验证成功');
  294. } catch (Exception $e) {
  295. return $this->error($e->getMessage());
  296. }
  297. }
  298. }
  299. public function actionGetUserConfig(){
  300. $user_setting = Yii::$app->services->setting->mall->get($this->mall_id, 'user');
  301. $data['is_manual_verification_code'] = $user_setting['is_manual_verification_code'] ?: 0;
  302. return $this->success('成功', $data);
  303. }
  304. public function actionGetDownloadUrl(){
  305. try{
  306. $channel = Yii::$app->services->setting->mall->get($this->mall_id, 'channel');
  307. $conf = $channel['app'] ?? [];
  308. if ($conf) {
  309. $conf = json_decode($conf, true);
  310. }
  311. $app['ios_download_url'] = $conf['ios_download_url'] ?? '';
  312. $app['android_download_url'] = $conf['android_download_url'] ?? '';
  313. return $this->success('请求成功', compact('app'));
  314. }catch(Exception $e){
  315. return $this->error($e->getMessage());
  316. }
  317. }
  318. /**
  319. * 获取配置的文本信息通用接口
  320. * @Author:lun
  321. * @Date:2023-12-22 11:37
  322. * @Copyright:copyright(c)2023 广东七件事集团
  323. * @return mixed|void|null
  324. */
  325. public function actionGetSettingValue()
  326. {
  327. $request = Yii::$app->request;
  328. if ($request->isGet) {
  329. $params = Yii::$app->request->get();
  330. $res = Yii::$app->services->validate->validate($params, [
  331. [['group','keyword'], 'required']
  332. ]);
  333. $group = $params['group'];
  334. $keyword = $params['keyword'];
  335. if ($res === false) throw new \Exception(Yii::$app->services->validate->getErrorMessage());
  336. $data = Yii::$app->services->setting->mall->get($this->mall_id, "{$group}.{$keyword}");
  337. return $this->success('获取成功',$data ?? '');
  338. }
  339. }
  340. public function actionCheckAppVersion()
  341. {
  342. if (Yii::$app->request->isGet) {
  343. $params = Yii::$app->request->get();
  344. $res = Yii::$app->services->validate->validate($params, [
  345. [['app_type'], 'required'],
  346. [['app_type'], 'string'],
  347. ]);
  348. if ($res === false) throw new \Exception(Yii::$app->services->validate->getErrorMessage());
  349. // $version_num = StringHelper::getVersionNum($params['version']);
  350. $data = AppVersion::find()->where(['app_type' => $params['app_type'], 'mall_id' => $this->mall_id, 'status' => StatusEnum::ENABLED])->orderBy('id desc')->asArray()->one();
  351. // var_dump($version_num < (int) $data['version_num']);exit;
  352. return $this->success('获取成功',['version' => $data['version'], 'version_num' => $data['version_num'], 'app_type' => $data['app_type'], 'download_url' => $data['download_url'], 'describe' => $data['content'], 'edition_force' => $data['edition_force'], 'package_type' => $data['package_type']]);
  353. // return $this->success('当前app为最新版本');
  354. }
  355. }
  356. /**
  357. * 地址解析(由文字地址到经纬度的转换能力,并同时提供结构化的省市区地址信息)
  358. * @Author: lun
  359. * @DateTime: 2023/7/20 0020 11:18
  360. * @Copyright: copyright (c) 2021 广东七件事集团
  361. * @return mixed|void
  362. */
  363. public function actionGeocoder()
  364. {
  365. $request = Yii::$app->request;
  366. if ($request->isPost) {
  367. $params = Yii::$app->request->post();
  368. $res = Yii::$app->services->validate->validate($params, [
  369. [['address'], 'required', 'message' => '请输入查询的详细地址'],
  370. [['address'], 'string'],
  371. ]);
  372. if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  373. $config = Yii::$app->services->setting->platform->get('map');
  374. if ($config['is_location'] == 0) {
  375. return $this->success('获取成功', []);
  376. }
  377. $data = QqMapHelper::Geocoder($params['address']);
  378. if ($data['status'] != 0) return $this->error($data['message']);
  379. return $this->success('获取成功', $data['result']);
  380. }
  381. }
  382. /**
  383. * 根据经纬度解析地址
  384. * @Author: lun
  385. * @DateTime: 2023/7/21 0021 14:33
  386. * @Copyright: copyright (c) 2021 广东七件事集团
  387. * @return mixed|void
  388. *
  389. */
  390. public function actionReverseGeocoder()
  391. {
  392. $request = Yii::$app->request;
  393. if ($request->isPost) {
  394. $params = Yii::$app->request->post();
  395. $res = Yii::$app->services->validate->validate($params, [
  396. [['longitude','latitude'], 'required', 'message' => '需要解析的经纬度不能为空'],
  397. [['longitude','latitude'], 'safe'],
  398. ]);
  399. if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  400. $config = Yii::$app->services->setting->platform->get('map');
  401. if ($config['is_location'] == 0) {
  402. return $this->success('获取成功', []);
  403. }
  404. $data = QqMapHelper::ReverseGeocoder($params['latitude'], $params['longitude']);
  405. if ($data['status'] != 0) return $this->error($data['message']);
  406. return $this->success('获取成功', $data['result']);
  407. }
  408. }
  409. /**
  410. * 根据当前经纬度获取附近的地点
  411. * @Author:lun
  412. * @Date:2025-01-15 09:22
  413. * @Copyright:copyright(c)2024 广东七件事集团
  414. * @return mixed|void|null
  415. */
  416. public function actionGetNear()
  417. {
  418. $request = Yii::$app->request;
  419. if ($request->isPost) {
  420. $params = Yii::$app->request->post();
  421. $res = Yii::$app->services->validate->validate($params, [
  422. [['longitude','latitude'], 'required', 'message' => '需要解析的经纬度不能为空'],
  423. [['longitude','latitude'], 'safe'],
  424. ]);
  425. if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  426. $data = QqMapHelper::getNearPlace($params['latitude'], $params['longitude']);
  427. return $this->success('获取成功', $data);
  428. }
  429. }
  430. }