SettingController.php 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892
  1. <?php
  2. namespace backend\modules\mall\controllers;
  3. use backend\controllers\MallController;
  4. use common\enums\AddonsEnum;
  5. use common\enums\AppEnum;
  6. use common\enums\GlobalFuncEnum;
  7. use common\enums\SettingEnum;
  8. use common\enums\StatusEnum;
  9. use common\enums\WechatPayTypeEnum;
  10. use common\enums\WithdrawEnum;
  11. use common\enums\WithdrawWayEnum;
  12. use common\enums\CartEnum;
  13. use common\enums\RabbitMqEnum;
  14. use common\globals\GlobalInvoke;
  15. use common\helpers\sms\Sms;
  16. use common\models\common\MallSetting;
  17. use common\models\common\ServiceAgreement;
  18. use common\models\goods\Goods;
  19. use common\models\mall\Mall;
  20. use common\models\mall\MallAddons;
  21. use common\models\order\OrderUnreadMsg;
  22. use common\models\user\User;
  23. use common\models\user\UserLevel;
  24. use Yii;
  25. use yii\helpers\Json;
  26. use common\models\common\Printer;
  27. use common\helpers\wechat\WechatTemplate;
  28. use common\models\user\UserFreezeCommission;
  29. use common\models\backend\Admin;
  30. use common\models\user\UserTeamProfitStatistics;
  31. class SettingController extends MallController
  32. {
  33. const AUTH_TAG_LENGTH_BYTE = 16;
  34. public $enableCsrfValidation = false;
  35. // 商城设置
  36. public function actionIndex()
  37. {
  38. return $this->render($this->action->id, [
  39. 'is_install_logistics' => MallAddons::isInstall($this->mall_id, AddonsEnum::ADDONS_NAME_LOGISTICS) ? StatusEnum::ENABLED : StatusEnum::DISABLED,
  40. 'mall_id' => $this->mall_id
  41. ]);
  42. }
  43. // 资产设置
  44. public function actionAssets()
  45. {
  46. $withdraw_cond = GlobalInvoke::exec(GlobalInvoke::INVOKE_GET_WITHDRAW_LIMIT_COND, $this->mall_id);
  47. $checked_condition_values = [];
  48. if (!empty($withdraw_cond)) {
  49. foreach ($withdraw_cond as $item) {
  50. $key = $item['addons_name'] . $item['id'];
  51. $value = [];
  52. if (!empty($item['render_setting']['setting'])) {
  53. foreach ($item['render_setting']['setting'] as $val) {
  54. if ($val['type'] == 'text') $value[$val['name']] = 0;
  55. }
  56. }
  57. $checked_condition_values[$key] = [
  58. 'key' => $key,
  59. 'value' => $value,
  60. ];
  61. }
  62. }
  63. $balanceWithdrawTotalWeightLimitOption = WithdrawEnum::BALANCE_WITHDRAW_TOTAL_WEIGHT_LIMIT_OPTION;
  64. return $this->render($this->action->id, [
  65. 'withdraw_cond' => $withdraw_cond,
  66. 'checked_condition_values' => json_encode($checked_condition_values),
  67. 'balance_withdraw_total_weight_limit_option' => json_encode($balanceWithdrawTotalWeightLimitOption),
  68. 'balance_withdraw_total_weight_limit_default_values' => json_encode(array_column($balanceWithdrawTotalWeightLimitOption, 'value'))
  69. ]);
  70. }
  71. // 会员设置
  72. public function actionUser()
  73. {
  74. return $this->render($this->action->id);
  75. }
  76. // 订单设置
  77. public function actionOrder()
  78. {
  79. return $this->render($this->action->id);
  80. }
  81. //购物车设置
  82. public function actionCart()
  83. {
  84. return $this->render($this->action->id);
  85. }
  86. // 编辑或获取配置信息
  87. public function actionEdit()
  88. {
  89. if (\Yii::$app->request->isAjax) {
  90. if (\Yii::$app->request->post()) {
  91. $setting = \Yii::$app->request->post('setting');
  92. if (empty($setting['withdraw_income']['level_withdrwas_reward']['value'])) $setting['withdraw_income']['level_withdrwas_reward']['value'] = [];
  93. if (!empty($setting['area']['area_limit']['value'])) {
  94. $setting['area']['area_limit']['value'] = json_decode($setting['area']['area_limit']['value'], true);
  95. }
  96. // 重新组合配置
  97. $data = self::makeUpParams($this->mall_id, $setting);
  98. // 修改当抵扣选择字段为空时默认存在
  99. if ($data['order'] && empty($data['order']['score_deduct_value_list'])) {
  100. $data['order']['score_deduct_value_list'] = [];
  101. }
  102. if ($data['order'] && empty($data['order']['achievement_goods_ids'])) {
  103. $data['order']['achievement_goods_ids'] = [];
  104. }
  105. if ($data['score'] && empty($data['score']['level_limit_levels'])) {
  106. $data['score']['level_limit_levels'] = [];
  107. }
  108. if ($data['order'] && !empty($data['order']['goods_deduct_list'])) {
  109. $data['order']['goods_deduct_list'] = [];
  110. }
  111. $is_reset_data = false;
  112. //如果业绩开关开启,且设置了业绩商品
  113. if (!empty($data['order']['achievement_goods_ids']) && $data['order']['is_designated_achievement_goods']) {
  114. $achievement_goods_ids = json_decode($data['order']['achievement_goods_ids'], true);
  115. //获取修改之前设置的商品数据
  116. $last_achievement_goods_ids = \Yii::$app->services->setting->mall->get($this->mall_id, 'order.achievement_goods_ids');
  117. //出现商品修改则需要重新累计数据
  118. if (!empty($last_achievement_goods_ids)) {
  119. $last_achievement_goods_ids = json_decode($last_achievement_goods_ids, true);
  120. $difference = array_diff($achievement_goods_ids, $last_achievement_goods_ids);
  121. } else {
  122. $difference = $achievement_goods_ids;
  123. }
  124. if (!empty($difference)) $is_reset_data = true;
  125. }
  126. !isset($data['withdraw_income']['balance_withdraw_total_weight_limit_selected']) && $data['withdraw_income']['balance_withdraw_total_weight_limit_selected'] = [];
  127. $res = Yii::$app->services->setting->mall->set($this->mall_id, $data);
  128. if ($res === false) return $this->error(Yii::$app->services->setting->mall->getError());
  129. if (($data['basic'] ?? false) && ($data['basic']['name'] ?? false)) {
  130. $mall_data['name'] = $data['basic']['name'];
  131. $mall_data['mall_id'] = $this->mall_id;
  132. MallSetting::editMallName($mall_data); //修改商城名称
  133. }
  134. if(UserFreezeCommission::getSwitchStatus($this->mall_id) == false) {
  135. UserFreezeCommission::clearUserData($this->mall_id);
  136. }
  137. //如果字段状态为true,对订单利润数据重新累计
  138. // if ($is_reset_data) {
  139. // Yii::$app->services->rabbitMq->push(RabbitMqEnum::EXCHANGE_LONG_DURATION, RabbitMqEnum::LONG_DURATION_QUEUE,
  140. // ['mall_id' => $this->mall_id], UserTeamProfitStatistics::class, 'orderProfit');
  141. // }
  142. $this->success('保存成功');
  143. } else {
  144. $params = \Yii::$app->request->get();
  145. // 检查提交的参数
  146. $res = Yii::$app->services->validate->validate($params, [
  147. [['type'], 'required'],
  148. [['type'], 'string']
  149. ]);
  150. if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  151. $mall_id = $this->mall_id;
  152. // 获取分组
  153. $groups = SettingEnum::getMallType($params['type']);
  154. $data = MallSetting::getConfByGroup($mall_id, $groups, true);
  155. $notice_wechat_template_message_list = WechatTemplate::getMap();
  156. unset($notice_wechat_template_message_list['store_order_pay_success']);
  157. $notice_wechat_template_message_value= [];
  158. if(!empty($data['notice_wechat']['template_message']['value'])){
  159. $notice_wechat_template_message_value = json_decode($data['notice_wechat']['template_message']['value'],true);
  160. if(isset($notice_wechat_template_message_value['commission_receipt'])) unset($notice_wechat_template_message_value['commission_receipt']);
  161. }
  162. foreach ($notice_wechat_template_message_list as $key=>$template_name){
  163. if(!isset($notice_wechat_template_message_value[$key])){
  164. $notice_wechat_template_message_value[$key] = ['tem_key'=>'', 'name'=>$template_name, 'tempid'=>'',];
  165. }
  166. }
  167. if(isset($notice_wechat_template_message_value['team_add'])) unset($notice_wechat_template_message_value['team_add']);
  168. if(isset($notice_wechat_template_message_value['order_refund_agree'])) unset($notice_wechat_template_message_value['order_refund_agree']);
  169. $data['notice_wechat']['template_message']['value'] = json_encode($notice_wechat_template_message_value);
  170. // 根据类型返回对应内容
  171. switch ($params['type']) {
  172. case SettingEnum::MALL_BASIC:
  173. $web_url = rtrim(\Yii::$app->services->setting->get('system.h5_url'), '/') . '/#/?sign=' . $this->mall['mall_sign'];
  174. $return = array_merge(self::returnArray($data), ['web_url' => $web_url]);
  175. break;
  176. case SettingEnum::MALL_USER:
  177. $user_level = UserLevel::getUserLevelArr($this->mall_id);
  178. $return = array_merge(self::returnArray($data), ['user_level' => $user_level]);
  179. break;
  180. case SettingEnum::MALL_ASSETS:
  181. if (empty(Yii::$app->services->setting->get('system.h5_url'))) {
  182. $data['recharge']['page_link']['value'] = '';
  183. } else {
  184. $data['recharge']['page_link']['value'] = rtrim(Yii::$app->services->setting->get('system.h5_url'), '/') . '/#/plugins/pages/center/recharge/recharge?sign=' . $this->mall['mall_sign'];
  185. }
  186. $default_withdraw_way = WithdrawWayEnum::getDefaultWithDrawWayMap(WithdrawWayEnum::WITHDRAW_TYPE_2);
  187. // 全局获取提现方式
  188. $extension_withdraw_way = GlobalInvoke::exec(
  189. GlobalInvoke::INVOKE_GET_WITHDRAW_EXTENSION_WAY,
  190. $this->mall_id,
  191. ['mall_id' => $this->mall_id]
  192. );
  193. $all_withdraw = array_merge($default_withdraw_way, $extension_withdraw_way);;
  194. $data['income_withdraw_way'] = $all_withdraw;
  195. unset($all_withdraw[WithdrawWayEnum::BALANCE]);
  196. // dd($all_withdraw);
  197. $data['balance_withdraw_way'] = $all_withdraw;
  198. //提现条件
  199. $checked_condition_values = [];
  200. if (!empty($data['withdraw_balance']['checked_condition_values']['value'])) {
  201. $checked_condition_values = json_decode($data['withdraw_balance']['checked_condition_values']['value'], true);
  202. }
  203. $withdraw_cond = GlobalInvoke::exec(GlobalInvoke::INVOKE_GET_WITHDRAW_LIMIT_COND, $this->mall_id);
  204. if (!empty($withdraw_cond)) {
  205. foreach ($withdraw_cond as $item) {
  206. $key = $item['addons_name'] . $item['id'];
  207. if (!isset($checked_condition_values[$key])) {
  208. $value = [];
  209. if (!empty($item['render_setting']['setting'])) {
  210. foreach ($item['render_setting']['setting'] as $val) {
  211. if ($val['type'] == 'text') $value[$val['name']] = 0;
  212. }
  213. }
  214. $checked_condition_values[$key] = [
  215. 'key' => $key,
  216. 'value' => $value,
  217. ];
  218. }
  219. }
  220. }
  221. $data['withdraw_balance']['checked_condition_values']['value'] = json_encode($checked_condition_values);
  222. if(!isset($data['withdraw_income']['is_login']['value'])){
  223. $data['withdraw_income']['is_login'] = $data['withdraw_income']['is_income_cash'];
  224. $data['withdraw_income']['is_login']['value'] = 0;
  225. $data['withdraw_income']['is_login']['name'] = 'is_login';
  226. }
  227. if(!isset($data['withdraw_income']['show_type']['value'])){
  228. $data['withdraw_income']['show_type']['value'] = 1;
  229. }
  230. $return = self::returnArray($data);
  231. // 公共调用
  232. $addons_list = GlobalInvoke::exec(GlobalInvoke::GET_INSTALL_ADDONS_LIST, $this->mall_id, [
  233. 'mall_id' => $this->mall_id,
  234. ]);
  235. $return['addons_list'] = $addons_list;
  236. break;
  237. default:
  238. $return = self::returnArray($data);
  239. break;
  240. }
  241. $return['mall_sign'] = $mall['mall_sign'] ?? '';
  242. if (!empty($return['balance_withdraw_way']['alipay_tax'])) {
  243. $return['balance_withdraw_way']['alipay_tax'] = $return['balance_withdraw_way']['alipay_tax']['name'];
  244. }
  245. if (!empty($return['income_withdraw_way']['alipay_tax'])) {
  246. $return['income_withdraw_way']['alipay_tax'] = $return['income_withdraw_way']['alipay_tax']['name'];
  247. }
  248. $return['user_levels'] = UserLevel::getUserLevel([['mall_id' => $this->mall_id], ['status' => StatusEnum::ENABLED]], [], true, 'id,level,name');
  249. // $return['user_levels'][] = ['id' => 0, 'level' => 0, 'name' => '普通用户'];
  250. $return['user_levels_normal'] = $return['user_levels'];
  251. array_unshift($return['user_levels_normal'], ['id' => 0, 'level' => 0, 'name' => MallSetting::getDefaultLevelName($mall_id)]);
  252. $return['is_withdraw_repurchase'] = isset(\Yii::$app->params['is_withdraw_repurchase']) ? \Yii::$app->params['is_withdraw_repurchase'] : false;
  253. //是否安装了优惠劵插件
  254. $is_installed_coupon = MallAddons::isInstall($this->mall_id, AddonsEnum::ADDONS_NAME_COUPON);
  255. $return['marketing']['is_install_coupon']['value'] = 0;
  256. if ($is_installed_coupon) {
  257. $return['marketing']['is_install_coupon']['value'] = 1;
  258. }
  259. //是否安装了红包插件
  260. $is_installed_redpack = MallAddons::isInstall($this->mall_id, AddonsEnum::ADDONS_NAME_REDPACK);
  261. $return['marketing']['is_installed_redpack']['value'] = 0;
  262. if ($is_installed_redpack) {
  263. $return['marketing']['is_installed_redpack']['value'] = 1;
  264. }
  265. $is_installed_devote = MallAddons::isInstall($this->mall_id, AddonsEnum::ADDONS_NAME_DEVOTE);
  266. if (!MallAddons::isInstall($this->mall_id, AddonsEnum::ADDONS_NAME_STORE)) {
  267. $return['cart']['install_o2o'] = 0;
  268. } else {
  269. $return['cart']['install_o2o'] = 1;
  270. }
  271. $return['cart_list'] = CartEnum::getMap();
  272. if (empty($data['cart']['cart_name'])) {
  273. $return['cart']['cart_name']['value'] = json_encode([1 =>['name' => $return['cart_list'][1], 'is_show' => 0], 2 => ['name' => $return['cart_list'][2], 'is_show' => 0]]);
  274. }
  275. $currency = [
  276. 'balance' => '余额', 'score' => '积分'
  277. ];
  278. if($is_installed_devote) $currency['frozen_devote'] = '贡献值';
  279. $return['currency_list'] = $currency;
  280. $return['digital']['install_devote']['value'] = $is_installed_devote ? 1 : 0;
  281. if(!MallAddons::isInstall($this->mall_id, AddonsEnum::ADDONS_NAME_REDPACK))
  282. {
  283. $return['user_reward_redpacket']['is_open']=0;
  284. }
  285. else
  286. {
  287. $return['user_reward_redpacket']['is_open']=1;
  288. }
  289. if (!empty($return['withdraw_income']['level_withdrwas_reward']['value'])) {
  290. $return['withdraw_income']['level_withdrwas_reward']['value'] = json_decode($return['withdraw_income']['level_withdrwas_reward']['value'], true);
  291. }
  292. if (!empty($return['order']['is_designated_achievement_goods']['value'])) {
  293. $goodsIds = json_decode($return['order']['achievement_goods_ids']['value'], true);
  294. if (!empty($goodsIds)) {
  295. $return['achievementGoodsList'] = Goods::lists(['where' => [['id' => $goodsIds]], 'select' => 'id, cover_pic, goods_name']);
  296. }
  297. }
  298. if($params['type']==SettingEnum::MALL_ORDER){
  299. $sun_single_default = MallSetting::getDefaultSunSingle();
  300. $sun_single = MallSetting::getConfByGroup($mall_id, 'sun_single', true);
  301. $sun_single = self::returnArray($sun_single);
  302. if(empty($sun_single['type']['value'])){
  303. $sun_single = $sun_single_default;
  304. }
  305. $return['sun_single'] = $sun_single;
  306. $scoreGiveSetting = json_decode($return['marketing']['score_give_setting']['value'],true);
  307. if(!isset($scoreGiveSetting['score_giving_goods_type'])){
  308. $scoreGiveSetting['score_giving_goods_type'] = [];
  309. }
  310. if(!isset($scoreGiveSetting['score_giving_calculation'])){
  311. $scoreGiveSetting['score_giving_calculation'] = 0;
  312. }
  313. $return['marketing']['score_give_setting']['value'] = json_encode($scoreGiveSetting);
  314. }
  315. $user_level_all = UserLevel::lists([
  316. 'where' => [
  317. ['mall_id' => $this->mall_id],
  318. ['<>' , 'status', StatusEnum::DELETE]
  319. ],
  320. 'order' => 'level',
  321. // 'index' => 'level',
  322. ], true);
  323. // $user_level_all[0] = ['name' => '普通会员', 'level' => 0];
  324. $return['user_level_all'] = $user_level_all;
  325. if (empty($return['withdraw_income']['indep_withdrwas_reward'])){
  326. $return['withdraw_income']['indep_withdrwas_reward'] = ['value' => []];
  327. } else {
  328. $return['withdraw_income']['indep_withdrwas_reward']['value'] = json_decode($return['withdraw_income']['indep_withdrwas_reward']['value'], true);
  329. }
  330. foreach ($return['user_level_all'] as $key => $value) {
  331. if (empty($return['withdraw_income']['indep_withdrwas_reward']['value'][$value['level']])) {
  332. $return['withdraw_income']['indep_withdrwas_reward']['value'][$value['level']] = [
  333. 'direct_withdraws_reward' => 0,
  334. 'indirect_withdraws_reward' => 0
  335. ];
  336. }
  337. }
  338. $return['order']['goods_deduct_list']['value'] = [];
  339. $return['order']['goods_deduct_list']['value'][] = ['name'=> '渠道分红', 'value' => 'agent'];
  340. if(MallAddons::isInstall($this->mall_id, AddonsEnum::ADDONS_NAME_AGENT_BASE)) {
  341. $return['order']['goods_deduct_list']['value'][] = [
  342. 'name'=> '渠道业绩',
  343. 'value' => 'agent_base'
  344. ];
  345. }
  346. $this->success('获取成功', $return);
  347. }
  348. }
  349. }
  350. /**
  351. * 数组重组
  352. * @param array $params
  353. * @return array
  354. */
  355. private static function makeUpParams($mallId, array $params)
  356. {
  357. $data = [];
  358. // 重新组合配置
  359. foreach ($params as $group => $value) {
  360. foreach ($value as $name => $val) {
  361. isset($val['value']) && $data[$group][$name] = is_array($val['value']) ? Json::encode($val['value']) : $val['value'];
  362. }
  363. }
  364. return $data;
  365. }
  366. /**
  367. * 字符串转数组
  368. * @param array $data
  369. * @param string $changeText
  370. * @return array
  371. */
  372. private static function returnArray(array $data, $changeText = 'checkbox')
  373. {
  374. foreach ($data as $key => $item) {
  375. foreach ($item as $k => $value) {
  376. $type = $value['type'] ?? '';
  377. if ($type == $changeText) {
  378. $data[$key][$k]['value'] = Json::decode($value['value'], true);
  379. }
  380. // 月份数组
  381. if (in_array($k, ['month', 'repurchase_user_level_limit', 'score_giving_goods_type'])) {
  382. !is_array($data[$key][$k]['value']) && $data[$key][$k]['value'] = Json::decode($value['value'], true);
  383. }
  384. }
  385. }
  386. return $data;
  387. }
  388. /**
  389. * 打印机设置
  390. * @param int $printer_id 打印机ID
  391. */
  392. public function actionPrinterSetting()
  393. {
  394. $printer_id = \Yii::$app->request->get('printer_id');
  395. $params['where'][] = ['=', 'printer_id', $printer_id];
  396. $params['where'][] = ['=', 'mall_id', $this->mall_id];
  397. $params['where'][] = ['=', 'is_delete', 0];
  398. $params['limit'] = 10;
  399. $pageData = Printer::listPage($params, false);
  400. array_walk($pageData['list'], function (&$v) {
  401. $v['type'] = json_decode($v['type'], true);
  402. });
  403. return $this->success('获取成功', $pageData);
  404. }
  405. public function actionPrinter()
  406. {
  407. if (\Yii::$app->request->isAjax) {
  408. $printer = Yii::$app->services->setting->mall->get($this->mall_id, 'printer.printer');
  409. return $this->success('操作成功', json_decode($printer));
  410. }
  411. return $this->render('printer');
  412. }
  413. /**
  414. * 编辑门店打印机设置
  415. * @param int 是否开启
  416. * @param json type 商户设置
  417. * @param int is_attr 是否使用规格
  418. * @param int store_id 门店ID
  419. * @param string name 打印机名字
  420. * @param int printer_id 打印机ID
  421. * @author hpei
  422. * @return mixed
  423. */
  424. public function actionEditPrinterSetting()
  425. {
  426. $params = \Yii::$app->request->post();
  427. $res = Yii::$app->services->validate->validate($params, [
  428. [['is_attr', 'status', 'type', 'store_id', 'name', 'printer_id'], 'required'],
  429. [['id'], 'safe']
  430. ]);
  431. if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  432. $params['mall_id'] = $this->mall_id;
  433. $res = Printer::editSetting($params);
  434. if ($res === false) return $this->error(Printer::getStaticError());
  435. return $this->success('保存成功');
  436. }
  437. /**
  438. * 获取打印机类型
  439. *
  440. * @author hpei
  441. * @return array
  442. */
  443. public function actionGetPrinterType()
  444. {
  445. $printerType = Printer::PRINTER_TYPE;
  446. return $this->success('获取成功', $printerType);
  447. }
  448. /**
  449. * 添加打印机
  450. *
  451. * @author hpei
  452. * @return mixed
  453. */
  454. public function actionEditPrinter()
  455. {
  456. $params = \Yii::$app->request->post();
  457. try {
  458. $printers = MallSetting::getConfByGroup($this->mall_id, 'printer', true);
  459. $printers = !empty($printers) && !empty($printers['printer']['value']) ? json_decode($printers['printer']['value'], true) : [];
  460. if (isset($params['id']) && !empty($params['id'])) {
  461. $printers = array_column($printers, null, 'id');
  462. if (!isset($printers[$params['id']])) throw new \Exception('打印机不存在');
  463. $printer['id'] = $params['id'];
  464. } else {
  465. $max_id = empty($printers) ? 1 : max(array_column($printers, 'id')) + 1;
  466. $printer['id'] = $max_id;
  467. }
  468. $printer['type'] = $params['type'];
  469. $printer['name'] = $params['name'];
  470. $printer['brand'] = $params['brand'];
  471. unset($params['type'], $params['name'], $params['brand'], $params['print_name'], $params['_csrf']);
  472. $printer['printer_config'] = $params;
  473. if (isset($params['id']) && !empty($params['id'])) {
  474. $printers[$params['id']] = $printer;
  475. $printers = array_values($printers);
  476. } else {
  477. array_push($printers, $printer);
  478. }
  479. Yii::$app->services->setting->mall->set($this->mall_id, ['printer' => ['printer' => $printers]]);
  480. return $this->success('添加成功');
  481. } catch (\Exception $e) {
  482. return $this->error($e->getMessage());
  483. }
  484. }
  485. /**
  486. * 删除打印机
  487. *
  488. * @author hpei
  489. * @return mixed
  490. */
  491. public function actionDelePrinter()
  492. {
  493. $id = \Yii::$app->request->post('id');
  494. try {
  495. $printer = Yii::$app->services->setting->mall->get($this->mall_id, 'printer.printer');
  496. if (empty($printer)) return $this->error('打印机不存在');
  497. $printer = json_decode($printer, true);
  498. $printer = array_column($printer, null, 'id');
  499. unset($printer[$id]);
  500. $printer = array_values($printer);
  501. Yii::$app->services->setting->mall->set($this->mall_id, ['printer' => ['printer' => $printer]]);
  502. Printer::deleSetting(['printer_id' => $id]);
  503. return $this->success('删除成功');
  504. } catch (\Exception $e) {
  505. return $this->error($e->getMessage());
  506. }
  507. }
  508. /**
  509. * 修改是否启用,是否使用规格
  510. *
  511. */
  512. public function actionChangePrinterSetting()
  513. {
  514. $params = \Yii::$app->request->post();
  515. $res = Yii::$app->services->validate->validate($params, [
  516. [['is_attr', 'status'], 'required'],
  517. [['id'], 'safe']
  518. ]);
  519. if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  520. $res = Printer::changeSetting($params);
  521. if ($res === false) return $this->error(Printer::getStaticError());
  522. return $this->success('修改成功');
  523. }
  524. /**
  525. * 删除打印机设置
  526. */
  527. public function actionDelePrinterSetting()
  528. {
  529. $id = \Yii::$app->request->post('id', '');
  530. if (empty($id)) {
  531. return $this->error('Id cannot be blank');
  532. }
  533. $params['id'] = $id;
  534. $res = Printer::deleSetting($params);
  535. if ($res === false) return $this->error(Printer::getStaticError());
  536. return $this->success('删除成功');
  537. }
  538. //测试短信发送
  539. public function actionSendSms()
  540. {
  541. try {
  542. $params = \Yii::$app->request->post();
  543. if (empty($params['mobile'])) return $this->error('请输入手机号码');
  544. $area_code = ''; // 初始化区号
  545. $gateways = 'domestic'; // 默认国内短信
  546. // 检测是登录并且区号不为空则使用国际短信
  547. if (!empty($this->user) && !empty($this->user->area_code)) {
  548. $gateways = 'international';
  549. $area_code = $this->user->area_code;
  550. }
  551. // 判断是否有区号
  552. if (!empty($params['area_code']) && $params['area_code'] != 86) {
  553. $gateways = 'international';
  554. $area_code = $params['area_code'];
  555. }
  556. $sms = new Sms($this->mall_id, $gateways);
  557. switch ($params['type']) {
  558. case 1:
  559. if ($sms->sendNewUser($params['mobile'], 'test', $area_code) === false) return $this->error('发送失败');
  560. break;
  561. case 2:
  562. if ($sms->sendOrderOn($params['mobile'], 'sxxxxxxxxxxxxxxxxxxxxxxxx', $area_code) === false) return $this->error('发送失败');
  563. break;
  564. case 3:
  565. if ($sms->sendRefundOrderOn($params['mobile'], 'rxxxxxxxxxxxxxxxxxxxxxxxx', $area_code) === false) return $this->error('发送失败');
  566. break;
  567. case 4:
  568. try {
  569. if ($sms->sendCaptcha($params['mobile'], $area_code) === false) return $this->error('发送失败');
  570. }catch (\Exception $e){
  571. return $this->error($e->getMessage());
  572. }
  573. break;
  574. case 5:
  575. if ($sms->sendUserLevelExpired($params['mobile'], 'nickname', $area_code) === false) return $this->error('发送失败');
  576. break;
  577. default:
  578. }
  579. return $this->success('发送成功');
  580. } catch (\Exception $e) {
  581. return $this->error($e->getMessage());
  582. }
  583. }
  584. private function createNoncestr($length = 32)
  585. {
  586. $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
  587. $str = "";
  588. for ($i = 0; $i < $length; $i++) {
  589. $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
  590. }
  591. return $str;
  592. }
  593. private function createAuthorization($url, $mch_id, $serial_no, $mch_private_key, $nonce, $http_method = 'GET')
  594. {
  595. if (!in_array('sha256WithRSAEncryption', openssl_get_md_methods(true))) {
  596. throw new \RuntimeException("当前PHP环境不支持SHA256withRSA");
  597. }
  598. $url_parts = parse_url($url);
  599. $canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));
  600. //私钥地址
  601. //商户号
  602. $merchant_id = $mch_id;
  603. //当前时间戳
  604. $timestamp = time();
  605. //随机字符串
  606. $body = '';
  607. //POST请求时 需要 转JSON字符串
  608. $message = $http_method . "\n" .
  609. $canonical_url . "\n" .
  610. $timestamp . "\n" .
  611. $nonce . "\n" .
  612. $body . "\n";
  613. //生成签名
  614. openssl_sign($message, $raw_sign, $mch_private_key, 'sha256WithRSAEncryption');
  615. $sign = base64_encode($raw_sign);
  616. //Authorization 类型
  617. $schema = 'WECHATPAY2-SHA256-RSA2048';
  618. //生成token
  619. $token = sprintf('mchid="%s",serial_no="%s",nonce_str="%s",timestamp="%d",signature="%s"', $merchant_id, $serial_no, $nonce, $timestamp, $sign);
  620. $header = [
  621. 'Content-Type:application/json',
  622. 'Accept:application/json',
  623. 'User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36',
  624. 'Authorization: ' . $schema . ' ' . $token
  625. ];
  626. return $header;
  627. }
  628. private function decryptToString($aesKey, $associatedData, $nonceStr, $ciphertext)
  629. {
  630. $ciphertext = \base64_decode($ciphertext);
  631. if (strlen($ciphertext) <= self::AUTH_TAG_LENGTH_BYTE) {
  632. return false;
  633. }
  634. // ext-sodium (default installed on >= PHP 7.2)
  635. if (
  636. function_exists('\sodium_crypto_aead_aes256gcm_is_available') &&
  637. \sodium_crypto_aead_aes256gcm_is_available()
  638. ) {
  639. return \sodium_crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $aesKey);
  640. }
  641. // ext-libsodium (need install libsodium-php 1.x via pecl)
  642. if (
  643. function_exists('\Sodium\crypto_aead_aes256gcm_is_available') &&
  644. \Sodium\crypto_aead_aes256gcm_is_available()
  645. ) {
  646. return \Sodium\crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $aesKey);
  647. }
  648. // openssl (PHP >= 7.1 support AEAD)
  649. if (PHP_VERSION_ID >= 70100 && in_array('aes-256-gcm', \openssl_get_cipher_methods())) {
  650. $ctext = substr($ciphertext, 0, -self::AUTH_TAG_LENGTH_BYTE);
  651. $authTag = substr($ciphertext, -self::AUTH_TAG_LENGTH_BYTE);
  652. return \openssl_decrypt(
  653. $ctext,
  654. 'aes-256-gcm',
  655. $aesKey,
  656. \OPENSSL_RAW_DATA,
  657. $nonceStr,
  658. $authTag,
  659. $associatedData
  660. );
  661. }
  662. throw new \RuntimeException('AEAD_AES_256_GCM需要PHP 7.1以上或者安装libsodium-php');
  663. }
  664. private function doGet($url, $header)
  665. {
  666. $curl = curl_init(); // 启动一个CURL会话
  667. curl_setopt($curl, CURLOPT_URL, $url);
  668. curl_setopt($curl, CURLOPT_HEADER, 0);
  669. curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  670. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // 跳过证书检查
  671. curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); // 从证书中检查SSL加密算法是否存在
  672. curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
  673. $data = curl_exec($curl);
  674. return json_decode($data, true);
  675. }
  676. //生成支付平台证书,用于商家打款到零钱
  677. public function actionCreatePayCredentials()
  678. {
  679. $url = "https://api.mch.weixin.qq.com/v3/certificates";
  680. $config = \Yii::$app->services->pay->getConfig($this->mall_id, 'wechat');
  681. $nonce = $this->createNoncestr();
  682. $header = $this->createAuthorization($url, $config['wechat_mch_id'], $config['wechat_serial'], $config['wechat_key_pem'], $nonce);
  683. //增加平台证书序列号 , 平台证书序列号方法 getcertificates()
  684. $header[] = 'Wechatpay-Serial:' . $config['wechat_serial'];
  685. $data = $this->doGet($url, $header);
  686. if (!empty($data['data'][0]['encrypt_certificate']['ciphertext'])) {
  687. $associated_data = $data['data'][0]['encrypt_certificate']['associated_data'];
  688. $ciphertext = $data['data'][0]['encrypt_certificate']['ciphertext'];
  689. $nonce = $data['data'][0]['encrypt_certificate']['nonce'];
  690. $res = $this->decryptToString($config['wechat_pay_secret_v3'], $associated_data, $nonce, $ciphertext);
  691. if (!empty($res)) {
  692. $dir = dirname(Yii::$app->basePath) . '/backend/runtime/pem/' . $this->mall_id;
  693. if (!is_dir($dir)) mkdir($dir, 0755,true);
  694. $file_name = $dir . '/wechatpay.pem';
  695. file_put_contents($file_name, $res);
  696. return $this->success('操作成功');
  697. }
  698. }
  699. if (!empty($data['message'])) {
  700. return $this->error($data['message']);
  701. }
  702. return $this->error('操作失败');
  703. }
  704. //重置未读消息
  705. public function actionOrderMsg()
  706. {
  707. // 查询会员订单信息
  708. $user_id = Yii::$app->request->get('user_id', '');
  709. $model = OrderUnreadMsg::findOne(['user_id' => $user_id, 'mall_id' => $this->mall_id]);
  710. $model->order_pay_num = 0;
  711. $model->order_received_num = 0;
  712. $model->order_goods_num = 0;
  713. $model->order_evaluate_num = 0;
  714. $model->order_return_num = 0;
  715. $model->save();
  716. if ($user_id) {
  717. $params['mall_id'] = $this->mall_id;
  718. $params['user_id'] = $user_id;
  719. $data = OrderUnreadMsg::orderStatistic($params);
  720. }
  721. echo '操作成功';
  722. }
  723. public function actionMemory()
  724. {
  725. return $this->render($this->action->id);
  726. }
  727. public function actionGetMemory()
  728. {
  729. if (\Yii::$app->request->isAjax) {
  730. if (\Yii::$app->request->post()) {
  731. $setting = \Yii::$app->request->post('setting');
  732. $trans = \Yii::$app->db->beginTransaction();
  733. try {
  734. $data = self::makeUpParams($this->mall_id, $setting);
  735. $res = Yii::$app->services->setting->mall->set($this->mall_id, $data);
  736. if ($res === false) return $this->error(Yii::$app->services->setting->mall->getError());
  737. $trans->commit();
  738. $this->success('操作成功');
  739. } catch (\Exception $e) {
  740. $trans->rollBack();
  741. \Yii::error('edit mallSetting error:' . $e->getMessage());
  742. $this->error('编辑失败');
  743. }
  744. } else {
  745. $params = \Yii::$app->request->get();
  746. // 检查提交的参数
  747. $res = Yii::$app->services->validate->validate($params, [
  748. [['type'], 'required'],
  749. [['type'], 'string']
  750. ]);
  751. if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  752. $mall_id = $this->mall_id;
  753. $groups = SettingEnum::getMallType($params['type']);
  754. $data = MallSetting::getConfByGroup($mall_id, $groups, true);
  755. $this->success('操作成功', $data);
  756. }
  757. }
  758. }
  759. /**
  760. * 获取商城h5链接
  761. * @Author: lun
  762. * @DateTime: 2023/6/20 0020 9:16
  763. * @Copyright: copyright (c) 2021 广东七件事集团
  764. * @return mixed|void
  765. */
  766. public function actionGetMallUrl()
  767. {
  768. if (Yii::$app->request->isAjax && Yii::$app->request->isGet) {
  769. $web_url = Yii::$app->services->setting->platform->get('system.h5_url');
  770. if (empty($web_url)) return $this->error('请设置域名');
  771. $h5_url = $web_url .'/#/?sign=' . $this->mall['mall_sign'];
  772. return $this->success('操作成功', $h5_url);
  773. }
  774. }
  775. public function actionGetCurrencyText(){
  776. if (Yii::$app->request->isAjax) {
  777. if(Yii::$app->request->isGet){
  778. $params = Yii::$app->request->get();
  779. $currency = $params['currency'];
  780. $score_name = \Yii::$app->services->setting->mall->get($this->mall_id, 'score.score_name') ?? '积分';
  781. $digital_name = \Yii::$app->services->setting->mall->get($this->mall_id, 'digital.name') ?? '数字币';
  782. $all_currency = [
  783. 'commission' => '佣金',
  784. 'digital' => $digital_name,
  785. 'score' => $score_name
  786. ];
  787. $data = [];
  788. foreach($currency as $v){
  789. if(isset($all_currency[$v])){
  790. $data[$v] = $all_currency[$v];
  791. }
  792. }
  793. return $this->success('数据请求成功', $data);
  794. }
  795. }
  796. }
  797. /**
  798. * 获取微信消息模版ID
  799. * @return mixed|void|null
  800. * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
  801. * @throws \GuzzleHttp\Exception\GuzzleException
  802. */
  803. public function actionGetWechatNotice()
  804. {
  805. if (Yii::$app->request->isAjax && Yii::$app->request->post()) {
  806. $params = Yii::$app->request->post();
  807. $res = Yii::$app->services->validate->validate($params, [
  808. [['key'], 'required'], [['key'], 'string']
  809. ]);
  810. if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  811. // 根据key获取对应的微信消息模板ID
  812. try {
  813. $data = MallSetting::getConfByGroup($this->mall_id, 'notice_wechat', true);
  814. $tempid = '';
  815. if(!empty($data['template_message']['value'])){
  816. $notice_wechat_template_message_value = json_decode($data['template_message']['value'],true);
  817. if(!empty($notice_wechat_template_message_value[$params['key']]['tempid'])){
  818. $tempid = $notice_wechat_template_message_value[$params['key']]['tempid'];
  819. }
  820. }
  821. $template = new WechatTemplate($this->mall_id);
  822. $response = $template->addTemplate($params['key'],$tempid);
  823. if ($response['errcode'] != 0) return $this->error('获取失败:' . $response['errmsg']);
  824. return $this->success('获取模板成功,记得左下角按钮进行保存哦', $response['template_id']);
  825. } catch (\Exception $e) {
  826. return $this->error('获取失败:' . $e->getMessage());
  827. }
  828. }
  829. }
  830. public function actionLoadExtraData()
  831. {
  832. try{
  833. $is_installed_fun_town = (int)MallAddons::isInstall($this->mall_id, AddonsEnum::ADDONS_NAME_FUN_TOWN);
  834. $data = compact('is_installed_fun_town');
  835. return $this->success('数据获取成功', $data);
  836. }catch(\Exception $e){
  837. return $this->error($e->getMessage());
  838. }
  839. }
  840. }