DefaultController.php 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522
  1. <?php
  2. namespace addons\ShareRedpack\api\modules\v1\controllers;
  3. use addons\ShareRedpack\common\enums\ShareRedpackEnum;
  4. use addons\ShareRedpack\common\models\ShareRedpack;
  5. use addons\ShareRedpack\common\models\ShareRedpackCode;
  6. use addons\ShareRedpack\common\models\ShareRedpackInvate;
  7. use addons\ShareRedpack\common\models\ShareRedpackInvateLog;
  8. use addons\ShareRedpack\common\models\ShareRedpackRecord;
  9. use addons\ShareRedpack\common\models\ShareRedpackRecordLog;
  10. use common\components\export\CsvTool;
  11. use common\enums\DiyEnum;
  12. use common\enums\RabbitMqEnum;
  13. use common\enums\StatusEnum;
  14. use common\models\common\Attachment;
  15. use common\models\common\PosterCode;
  16. use common\models\user\User;
  17. use common\events\census\ShareEvent;
  18. use common\models\user\UserWallet;
  19. use Exception;
  20. use services\common\UserWalletService;
  21. use Yii;
  22. use api\controllers\OnAuthController;
  23. use yii\helpers\Json;
  24. /**
  25. * 默认控制器
  26. *
  27. * Class DefaultController
  28. * @package addons\ShareRedpack\api\modules\v1\controllers
  29. */
  30. class DefaultController extends OnAuthController
  31. {
  32. public $modelClass = '';
  33. /**
  34. * 不用进行登录验证的方法
  35. *
  36. * 例如: ['index', 'update', 'create', 'view', 'delete']
  37. * 默认全部需要验证
  38. *
  39. * @var array
  40. */
  41. protected $authOptional = ['index','share-redpack-popup'];
  42. /**
  43. * 首页
  44. *
  45. * @return string
  46. */
  47. public function actionIndex()
  48. {
  49. return 'Hello world';
  50. }
  51. /**
  52. * 海报分享列表
  53. * @DateTime: 2021/12/24 0024 15:19
  54. * @Copyright: copyright (c) 2021 广东七件事集团
  55. * @return mixed|void
  56. */
  57. public function actionShareList()
  58. {
  59. $retuest = Yii::$app->request;
  60. if ($retuest->isPost) {
  61. $mall_id = $this->mall_id;
  62. $sign = $this->mall['mall_sign'];
  63. $where[] = ['=', 'status', StatusEnum::ENABLED];
  64. $where[] = ['=', 'mall_id', $mall_id];
  65. $select = "id,name,key_word,poster_content";
  66. $params = ['where' => $where, 'order' => 'id desc', 'select' => $select];
  67. $list = ShareRedpack::lists($params);
  68. if (empty($list)) return $this->success('获取成功', $list);
  69. foreach ($list as $key => $item) {
  70. $data = [
  71. 'user_id' => $this->user_id,
  72. 'nickname' => $this->user->nickname,
  73. 'avatar_url' => $this->user->avatar_url,
  74. 'item_id' => $item['id'],
  75. ];
  76. // 生成海报对应码
  77. $select_code = "id,mall_id,user_id,source,code,content,applet_code";
  78. if ($key == 0) $select_code.= ",applet_code";
  79. $poster = PosterCode::setData($this->mall_id, $this->user->id, User::SOURCE_SHARE_REDPACK, $data, $select_code);
  80. $sharePoster = ShareRedpackCode::setData($this->mall_id, $this->user->id, User::SOURCE_SHARE_REDPACK, $data, $select_code,$poster['code']);
  81. if ($poster == false) return $this->error(ShareRedpackCode::getStaticError());
  82. $list[$key]['poster_code_id'] = $poster['id'];
  83. // $list[$key]['qrcode_url'] = DiyEnum::HOME_PAGE_PATH . "?sign={$sign}&parent_id=" . $this->user->id."&source=".User::SOURCE_SHARE_REDPACK;
  84. $list[$key]['qrcode_url'] = DiyEnum::USER_LOGIN . "?sign={$sign}&scene=" . $poster['code'];
  85. // 第一张图片请求获取小程序二维码
  86. if ($this->platform == User::PLATFORM_MP_WX && $key == 0 && empty($poster['applet_code'])) {
  87. //二维码携带user_id 跟活动类型
  88. // $codeParams = 'parent_id='.$this->user_id.'&'.'source='.User::SOURCE_SHARE_REDPACK;
  89. // $codeParams = $this->user_id.'&'.User::SOURCE_SHARE_REDPACK;
  90. $applet_url = $this->getAppletQrCode(DiyEnum::USER_LOGIN , $poster['code']);// 获取小程序二维码base64数据
  91. // $applet_url = $this->getAppletQrCode(DiyEnum::USER_LOGIN , $codeParams);// 获取小程序二维码base64数据
  92. if ($applet_url == false) return $this->error('获取小程序二维码失败');
  93. $list[$key]['applet_code'] = $applet_url;
  94. ShareRedpackCode::setData($this->mall_id, $this->user->id, User::SOURCE_SHARE_REDPACK, array_merge($data,['id' => $sharePoster['id'], 'applet_code' => $applet_url]), $select_code,$poster['code']);
  95. PosterCode::setData($this->mall_id, $this->user->id, User::SOURCE_SHARE_REDPACK, array_merge($data,['id' => $poster['id'], 'applet_code' => $applet_url]), $select_code);
  96. }
  97. if ($key == 0) {
  98. // 统计浏览次数
  99. ShareRedpack::updateAllCounters(['look_num' => 1],"id=" . $item['id']);
  100. }
  101. }
  102. //生成邀请详情表数据
  103. $findInvate = ShareRedpackInvate::findOne(['mall_id'=>$this->mall_id,'user_id'=>$this->user_id]);
  104. if(empty($findInvate)){
  105. $invateCode = $this->randomkeys(2);
  106. $invateModel = new ShareRedpackInvate();
  107. $invateModel->mall_id = $this->mall_id;
  108. $invateModel->user_id = $this->user_id;
  109. $invateModel->invite_code = $invateCode;
  110. $invateModel->num = 0;
  111. if(!$invateModel->save()){
  112. return $this->error($invateModel->getStaticError());
  113. }
  114. }
  115. //浏览
  116. $event = new ShareEvent($this->mall_id);
  117. $data['mall_id'] =$this->mall_id;
  118. \Yii::$app->services->events->dispatch($event, ['mall_id'=>$this->mall_id,'user_id'=>$this->user_id], $event->listeners);
  119. $this->success('获取成功', $list);
  120. }
  121. }
  122. /**
  123. * 获取海报码详情
  124. * @Author: lun
  125. * @DateTime: 2021/12/30 0030 14:07
  126. * @Copyright: copyright (c) 2021 广东七件事集团
  127. * @return mixed|void
  128. */
  129. public function actionPosterCodeDetail()
  130. {
  131. $retuest = Yii::$app->request;
  132. if ($retuest->isPost) {
  133. $params = \Yii::$app->request->post();
  134. $res = \Yii::$app->services->validate->validate($params, [
  135. [['scene'], 'string'],
  136. [['poster_code_id'], 'integer'],
  137. ]);
  138. if ($res === false) return $this->error(\Yii::$app->services->validate->getErrorMessage());
  139. $mall_id = $this->mall_id;
  140. $is_save = false;
  141. !empty($params['poster_code_id']) && $where['id'] = $params['poster_code_id'];
  142. $where['mall_id'] = $mall_id;
  143. !empty($params['scene']) && $where['code'] = $params['scene'];
  144. $where['status'] = StatusEnum::ENABLED;
  145. $select = "id,applet_code,user_id,source,item_id,source,content";
  146. $detail = ShareRedpackCode::find()->select($select)->where($where)->one();
  147. if (empty($detail)) return $this->error('暂无内容');
  148. if (!empty($params['poster_code_id']) && $this->platform == User::PLATFORM_MP_WX) {
  149. // 小程序二维码为空则去获取小程序二维码
  150. if (empty($detail['applet_code'])) {
  151. //二维码携带user_id 跟活动类型
  152. // $codeParams = 'parent_id='.$detail->user_id.'&'.'source='.User::SOURCE_SHARE_REDPACK;
  153. $applet_url = $this->getAppletQrCode(DiyEnum::USER_LOGIN, $detail['code']);// 获取小程序二维码base64数据
  154. // $applet_url = $this->getAppletQrCode(DiyEnum::USER_LOGIN, $codeParams);// 获取小程序二维码base64数据
  155. if ($applet_url == false) $this->error('获取小程序二维码失败');
  156. // 获取到base64将其临时存服务器
  157. $detail->applet_code = $applet_url;
  158. $is_save = true;
  159. }
  160. }
  161. // 统计浏览次数
  162. if (!empty($params['poster_code_id'])) {
  163. ShareRedpack::updateAllCounters(['look_num' => 1],"id=" . $detail->item_id);
  164. }
  165. // 统计海报扫码次数
  166. if (!empty($params['scene']) && $detail['source'] == User::SOURCE_SHARE_REDPACK) {
  167. ShareRedpack::updateAllCounters(['scan_code_num' => 1],"id=" . $detail->item_id);
  168. }
  169. // 保存数据
  170. if ($is_save && !$detail->save()) return $this->error("获取错误:" . ShareRedpackCode::getStaticError());
  171. // 解析json
  172. $content = Json::decode($detail['content'], true);
  173. if (!empty($content['user_id'])) {
  174. $content = array_merge(['share_user_id' => $content['user_id']], $content);
  175. $user = User::findOne(['id'=>$content['user_id']]);
  176. $content['invite_mobile'] = $user['mobile']??'';
  177. $detail['content'] = Json::encode($content);
  178. }
  179. $this->success('获取成功', $detail->toArray());
  180. }
  181. }
  182. /**
  183. * 红包设置页面
  184. */
  185. public function actionRedPacketSettingPage()
  186. {
  187. $retuest = Yii::$app->request;
  188. if ($retuest->isPost) {
  189. //获取用户余额
  190. $userWallet = UserWallet::findOne(['mall_id'=>$this->mall_id, 'user_id'=>$this->user_id]);
  191. $balance = 0;
  192. if(!empty($userWallet)){
  193. $balance = $userWallet->balance;
  194. }
  195. $data = [];
  196. $data['head_title'] = '发红包';
  197. $data['red_packet_text'] = '红包记录';
  198. $data['amount_text'] = '单个红包金额';
  199. $data['number_text'] = '红包个数';
  200. $data['balance'] = $balance;
  201. $data['button_text'] = '塞钱进红包(从余额中扣款)';
  202. $data['notes'] = '红包扣款源于您的消费钱包余额';
  203. $this->success('获取成功', $data);
  204. }
  205. }
  206. /**
  207. * 红包设置(发红包)
  208. */
  209. public function actionRedPacketSetting()
  210. {
  211. $retuest = Yii::$app->request;
  212. if ($retuest->isPost) {
  213. $params = \Yii::$app->request->post();
  214. $res = \Yii::$app->services->validate->validate($params, [
  215. [['money','num','id'], 'required'],
  216. [['money'], 'double'],
  217. [['num','id'], 'integer'],
  218. ]);
  219. if ($res === false) return $this->error(\Yii::$app->services->validate->getErrorMessage());
  220. if ($params['money'] < 0.01) return $this->error("金额必须大于或等于一分钱",['recharge_balance'=>0]);
  221. //获取用户钱包数据
  222. $walletData = UserWallet::findOne(['mall_id'=>$this->mall_id,'user_id'=>$this->user_id]);
  223. $allMoney = $params['money'] * $params['num'];
  224. if($walletData->balance < $allMoney) return $this->error("红包余额不足,请前往余额充值",['recharge_balance'=>1]);
  225. $trans = Yii::$app->db->beginTransaction();
  226. try {
  227. //生成红包活动
  228. $RedpackRecord = ShareRedpackRecord::findOne(['mall_id'=>$this->mall_id,'user_id'=>$this->user_id]);
  229. if(empty($RedpackRecord)){
  230. $RedpackRecord = new ShareRedpackRecord();
  231. }else{
  232. //判断红包个数是否消费完
  233. if($RedpackRecord->num > 0){
  234. return $this->error("还有剩余的红包".$RedpackRecord->num.'个未领取',['recharge_balance'=>0]);
  235. }
  236. }
  237. $RedpackRecord->mall_id = $this->mall_id;
  238. $RedpackRecord->user_id = $this->user_id;
  239. $RedpackRecord->money = $params['money'];
  240. $RedpackRecord->all_num = $params['num'];
  241. $RedpackRecord->num = $params['num'];
  242. $RedpackRecord->repack_id = $params['id'];
  243. if(!$RedpackRecord->save()){
  244. throw new Exception(ShareRedpackRecord::getStaticError());
  245. }
  246. //扣除用户余额
  247. $insert_wallet [] = ['mall_id' => $this->mall_id, 'user_id' => $this->user_id,
  248. 'is_frozen' => false,
  249. 'wallet_type' => UserWalletService::WALLET_TYPE_BALANCE,
  250. 'money' => '-'.$allMoney,
  251. 'desc' => '分享海报得红包',
  252. 'source_table' => ShareRedpackRecord::tableName(),
  253. 'source_table_id' => $this->user_id,
  254. 'from_type' => ShareRedpackEnum::FROM_SHARE_REDPACK,
  255. 'capital_type' => ShareRedpackEnum::SHARE_REDPACK_SETTING,
  256. ];
  257. $res = UserWalletService::batchHandleByQueue($insert_wallet);
  258. if ($res == false) throw new Exception(UserWalletService::getStaticError());
  259. $trans->commit();
  260. return $this->success('操作成功',['recharge_balance'=>0]);
  261. } catch (\Exception $e) {
  262. $trans->rollBack();
  263. return $this->error($e->getMessage());
  264. }
  265. }
  266. }
  267. /**
  268. * 红包记录列表(领取红包的时候会生成记录)
  269. */
  270. public function actionRedPacketList()
  271. {
  272. if (Yii::$app->request->isPost) {
  273. $params = Yii::$app->request->post();
  274. $where = [];
  275. $where[] = ['=', 'mall_id', $this->mall_id];
  276. $where[] = ['=', 'user_id', $this->user_id];
  277. $where[] = ['=', 'status', StatusEnum::ENABLED];
  278. $order = 'id desc';
  279. $select = "id,user_id,get_user_id,change_num,change_type,desc,created_at";
  280. $limit = $params['limit'] ?? 20;
  281. $with = ['user'];
  282. $params = compact('where','order','select','limit','with');
  283. // $params = ['select' => $select, 'where' => $where, 'order' => $order, 'with'=>$with];
  284. $list = ShareRedpackRecordLog::listPage($params, false, true);
  285. if(!empty($list['list'])){
  286. foreach ($list['list'] as &$item){
  287. $item['created_at'] = date('Y-m-d H:i:s',$item['created_at']);
  288. $item['desc'] = '发给用户:'.$item['user']['id'].' '.$item['user']['nickname'];
  289. }
  290. }
  291. unset($list['sql']);
  292. return $this->success('获取成功', compact('list'));
  293. }
  294. }
  295. /**
  296. * 登录判断是否显示红包弹框
  297. */
  298. public function actionShareRedpackPopup()
  299. {
  300. if (Yii::$app->request->isPost && $this->user_id) {
  301. //登录调用
  302. //判断用户来源
  303. $userData = User::findOne(['id' => $this->user_id]);
  304. $data = [];
  305. $data['is_open'] = 0;
  306. if ($userData->source == ShareRedpackEnum::SOURCE_SHARE_REDPACK) {
  307. //判断是否领取
  308. $find = ShareRedpackRecordLog::findOne(['get_user_id' => $this->user_id]);
  309. $record = ShareRedpackRecord::findOne(['mall_id'=>$this->mall_id, 'user_id'=>$userData->parent_id]);
  310. if (empty(($find)) && !empty($record)) {
  311. $data['is_open'] = 1;
  312. }
  313. }
  314. return $this->success('操作成功',$data);
  315. }
  316. }
  317. /**
  318. * 用户登录获取红包
  319. */
  320. public function actionGetRedpack()
  321. {
  322. if (Yii::$app->request->isPost) {
  323. //登录调用
  324. //判断用户来源
  325. $userData = User::findOne(['id'=>$this->user_id]);
  326. if($userData->source == ShareRedpackEnum::SOURCE_SHARE_REDPACK){
  327. //判断是否领取
  328. $find = ShareRedpackRecordLog::findOne(['get_user_id' => $this->user_id]);
  329. $record = ShareRedpackRecord::findOne(['mall_id'=>$this->mall_id, 'user_id'=>$userData->parent_id]);
  330. $trans = Yii::$app->db->beginTransaction();
  331. try {
  332. $data = [];
  333. if (empty($find) && !empty($record)) {
  334. $model = new ShareRedpackRecordLog();
  335. $model->record_id = $record->id;
  336. $model->mall_id = $this->mall_id;
  337. $model->user_id = $userData->parent_id;
  338. $model->get_user_id = $this->user_id;
  339. $model->change_num = $record->money;
  340. $model->change_type = 'sub';
  341. $model->desc = '发给用户:'.$userData->id.$userData->nickname;
  342. if (!$model->save()) {
  343. throw new Exception($model->getStaticError());
  344. }
  345. //红包数量-1
  346. $num = $record->num - 1;
  347. if ($num < 0) {
  348. return $this->error('来慢了,红包已被领取完');
  349. }
  350. $record->num = $num;
  351. if (!$record->save()) {
  352. throw new Exception($record->getStaticError());
  353. }
  354. //海报扫码次数加一
  355. $shareRepack = ShareRedpack::findOne(['id'=>$record->repack_id]);
  356. if(!empty($shareRepack)){
  357. $shareRepack->scan_code_num = $shareRepack->scan_code_num+1;
  358. if (!$shareRepack->save()) {
  359. throw new Exception($shareRepack->getStaticError());
  360. }
  361. }
  362. //增加用户余额
  363. $insert_wallet [] = ['mall_id' => $this->mall_id, 'user_id' => $this->user_id,
  364. 'is_frozen' => false,
  365. 'wallet_type' => UserWalletService::WALLET_TYPE_BALANCE,
  366. 'money' => $record->money,
  367. 'desc' => '分享海报得红包',
  368. 'source_table' => ShareRedpackRecord::tableName(),
  369. 'source_table_id' => $this->user_id,
  370. 'from_type' => ShareRedpackEnum::FROM_SHARE_REDPACK,
  371. 'capital_type' => ShareRedpackEnum::SHARE_REDPACK_SETTING,
  372. ];
  373. $res = UserWalletService::batchHandleByQueue($insert_wallet);
  374. if ($res == false) throw new Exception(UserWalletService::getStaticError());
  375. //share_redpack_invate 邀请数量 +1
  376. $invateModel = ShareRedpackInvate::findOne(['user_id'=>$userData->parent_id]);
  377. if(!empty($invateModel)){
  378. $invateModel->num = $invateModel->num + 1;
  379. if(!$invateModel->save()) throw new Exception($invateModel->getStaticError());
  380. //share_redpack_invate_log 生成邀请记录
  381. $invateLogModel = new ShareRedpackInvateLog();
  382. $invateLogModel->mall_id = $this->mall_id;
  383. $invateLogModel->invate_id = $invateModel->id;
  384. $invateLogModel->user_id = $this->user_id;
  385. if(!$invateLogModel->save()) throw new Exception($invateLogModel->getStaticError());
  386. }
  387. $data['desc'] = '恭喜您获得好友发放的红包';
  388. $data['money'] = $record->money.'元';
  389. }
  390. $trans->commit();
  391. return $this->success('操作成功',$data);
  392. } catch (\Exception $e) {
  393. $trans->rollBack();
  394. return $this->error($e->getMessage());
  395. }
  396. }
  397. }
  398. }
  399. function randomkeys($length)
  400. {
  401. $key = '';
  402. $pattern = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLOMNOPQRSTUVWXYZ';
  403. $time = time();
  404. $number = substr($time,6,4);
  405. for($i=0;$i<=$length;$i++)
  406. {
  407. $key .= $pattern[mt_rand(0,35)]; //生成php随机数
  408. }
  409. return $key.$number;
  410. }
  411. /**
  412. * 获取小程序二维码
  413. * @Author: lun
  414. * @DateTime: 2021/12/27 0027 17:25
  415. * @Copyright: copyright (c) 2021 广东七件事集团
  416. * @param $page
  417. * @param $scene
  418. * @return mixed|void
  419. */
  420. public function getAppletQrCode($page, $scene)
  421. {
  422. $page = ltrim($page, '/');
  423. $url = '';
  424. /** @var Wechat $wechat */
  425. Yii::$app->params['wechatMiniProgramConfig'] = Yii::$app->services->setting->mall->get($this->mall_id, 'mini_program');
  426. $miniProgram = Yii::$app->wechat->miniProgram;
  427. $response = $miniProgram->app_code->getUnlimit($scene, ['width' => 200, 'page' => $page]);
  428. if ($response instanceof \EasyWeChat\Kernel\Http\StreamResponse) {
  429. if (in_array('image/jpeg', $response->getHeader('Content-Type'))) {
  430. //返回base64图片
  431. $content = 'data:image/jpg;base64,'. base64_encode($response->getBody()->getContents());
  432. $path = Yii::getAlias('@attachment') . '/download/qrcode';
  433. if (!file_exists($path)) {// 异步生成小程序图片文件夹
  434. Yii::$app->services->rabbitMq->push(RabbitMqEnum::EXCHANGE_TASK, RabbitMqEnum::TASK_QUEUE, ['path' => $path], PosterCode::class, 'mkdirQrcode');
  435. }
  436. $fileName = $this->base64_image_content($content, $path);
  437. if ($fileName == false) return false;
  438. // 图片上传到云存储
  439. $csv = new CsvTool();
  440. $url = $csv->upload($this->mall_id, 'download/qrcode/' . $fileName);
  441. $config = Yii::$app->services->attachment->getStorageConfig($this->mall_id);
  442. if ($config['drive'] != Attachment::DRIVE_LOCAL) unlink($path .'/'. $fileName);// 删除临时存储的文件
  443. } else {
  444. //返回文字
  445. // $res = Json::decode($response->getBody()->getContents(), true);
  446. return $this->error('获取失败:' . $response->getBody()->getContents());
  447. // return false;
  448. }
  449. }else{
  450. return $this->error($response['errmsg']);
  451. // return false;
  452. }
  453. return $url;
  454. }
  455. function base64_image_content($base64_image_content,$path, $fileName = ''){
  456. try {
  457. //匹配出图片的格式
  458. if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $base64_image_content, $result)){
  459. $type = $result[2];
  460. if(!file_exists($path)){
  461. //检查是否有该文件夹,如果没有就创建,并给予最高权限
  462. mkdir($path, 0777, true);
  463. }
  464. $fileName = !empty($fileName) ? $fileName : md5(microtime(true));
  465. if (file_put_contents($path . '/' . $fileName. ".{$type}", base64_decode(str_replace($result[1],'', $base64_image_content)))){
  466. return $fileName . ".{$type}";
  467. }else{
  468. return false;
  469. }
  470. }else{
  471. return false;
  472. }
  473. } catch (\Exception $e) {
  474. // echo $e->getMessage();
  475. return false;
  476. }
  477. }
  478. }