UserService.php 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. <?php
  2. /**
  3. * 描述.
  4. *
  5. * @author nj
  6. * @date 2021-07-10 16:47
  7. */
  8. namespace Modules\InnerApi\Services;
  9. use App\Constants\RedisKeysConstant;
  10. use App\Events\InnerUserNewIncEvent;
  11. use App\Jobs\UserHyperLogLogJob;
  12. use App\Models\Mongo\UsersModel;
  13. use App\Repositories\AgentRepository;
  14. use App\Repositories\AppDeductionRuleRepository;
  15. use App\Repositories\ConfigRepoistory;
  16. use Carbon\Carbon;
  17. use Illuminate\Support\Facades\Redis;
  18. use Zhuzhichao\IpLocationZh\Ip;
  19. class UserService
  20. {
  21. /**
  22. * 缓存时间
  23. * @var int
  24. */
  25. private $cacheTime = 300;
  26. /**
  27. * 增量写入新用户.
  28. * @param array $data
  29. * @return mixed
  30. */
  31. public function inc(array $data)
  32. {
  33. $eventParams = [];
  34. foreach ($data as $item) {
  35. $item['created_at'] = Carbon::parse($item['created_at']);
  36. $item['invite_uid'] = !empty($item['invite_uid']) ? $item['invite_uid'] : '';
  37. if ($item['invite_uid'] == $item['user_uid']) {
  38. // 不能等于自己.
  39. $item['invite_uid'] = '';
  40. }
  41. $ipInfo = Ip::find($item['ip']);
  42. $item['ip_address'] = $ipInfo[0] . ' ' . $ipInfo[1] . ' ' . $ipInfo[2];
  43. $logObj = UsersModel::create($item);
  44. if (!empty($logObj->_id)) {
  45. $eventParams[] = [
  46. 'log_id' => $logObj->_id,
  47. ];
  48. }
  49. }
  50. // 新用户注册时,也算一次登录.
  51. self::login($data);
  52. // 触发事件.
  53. event(new InnerUserNewIncEvent($eventParams));
  54. return true;
  55. }
  56. /**
  57. * 登录
  58. * @param array $data
  59. * @return bool
  60. */
  61. public function login(array $data)
  62. {
  63. // 丢job构造函数时,必须精简数据.
  64. $jobData = [];
  65. if (!empty($data)) {
  66. foreach ($data as $item) {
  67. $jobData[] = [
  68. 'agent_uid' => $item['agent_uid'],
  69. 'channel_uid' => $item['channel_uid'],
  70. 'created_at' => $item['created_at'],
  71. 'device_type' => $item['device_type'],
  72. 'mom_app_uid' => $item['mom_app_uid'],
  73. 'user_uid' => $item['user_uid'],
  74. ];
  75. }
  76. }
  77. if (!empty($jobData)) {
  78. dispatch(new UserHyperLogLogJob($jobData));
  79. }
  80. return true;
  81. }
  82. /**
  83. * 随机扣量标记. cpa扣量
  84. * @param array $item
  85. * @return array
  86. */
  87. public function oneRandDeduction(array $item)
  88. {
  89. $item['is_deduction'] = 0;
  90. //获取代理扣量配置
  91. $deductionConfig = app(ConfigRepoistory::class)->pickByKeys(['preferential_user', 'cpa_deduction_switch'], 'sys');
  92. if ($deductionConfig['cpa_deduction_switch']['svalue'] == 0) {
  93. return $item;
  94. }
  95. $iTodayRegUser = UsersModel::where('channel_uid', $item['channel_uid'])->count();
  96. //每日前几单不扣
  97. if ($iTodayRegUser < $deductionConfig['preferential_user']['svalue']) {
  98. return $item;
  99. }
  100. $agentInfo = app(AgentRepository::class)->findBy('uid', $item['agent_uid'], ['deduction_switch', 'cpa_deduction_rule']);
  101. if ($agentInfo->deduction_switch == 2 && !empty($agentInfo->cpa_deduction_rule)) {
  102. $item['is_deduction'] = $this->isDeduction($item, $agentInfo->cpa_deduction_rule);
  103. } else if ($agentInfo->deduction_switch == 0 || $agentInfo->deduction_switch == 3) {
  104. //获取扣量规则
  105. $rulesInfo = app(AppDeductionRuleRepository::class)->findByWhere(['app_uid' => $item['mom_app_uid'], 'deduction_type' => 'cpa'], ['deduction_pro']);
  106. if (empty($rulesInfo)) {
  107. return $item;
  108. }
  109. if ($agentInfo->deduction_switch == 3) {
  110. $method = 3;
  111. } else {
  112. $method = 1;
  113. }
  114. //超过每日设定的默认单就开始扣量
  115. $item['is_deduction'] = $this->isDeduction($item, $rulesInfo->deduction_pro, $method);
  116. } else {
  117. $item['is_deduction'] = 0;
  118. }
  119. return $item;
  120. }
  121. /**
  122. * 扣量
  123. *
  124. * @param $item
  125. * @param $deductionPro
  126. * @param $method
  127. * @return int|mixed
  128. */
  129. private function isDeduction($item, $deductionPro, $method = '')
  130. {
  131. $isDeduction = 0;
  132. //设置扣量参数
  133. $ratio = $deductionPro;
  134. $ratio = explode('-',$ratio);
  135. if ($ratio[1] == 0) {
  136. return $isDeduction;
  137. }
  138. $hashKey = RedisKeysConstant::DEDUCTION_RULES_HASH_CPA . $item['mom_app_uid'] . $item['channel_uid'] . $method;
  139. //扣量标记
  140. $areaKey = $item['channel_uid'];
  141. $deductionMark = Redis::hget($hashKey, $areaKey);
  142. $mark = [0,0];
  143. if ($deductionMark) {
  144. $mark = explode('-', $deductionMark);
  145. if ($mark[0] == $ratio[0] && $mark[1] == $ratio[1]) {
  146. Redis::hDel($hashKey, $areaKey);
  147. $mark = [0,0];
  148. }
  149. //如果扣量达到,但是一轮还没结束则直接返回
  150. if ($mark[1] == $ratio[1]) {
  151. // $mark[0] + 1 参与订单总数加1
  152. Redis::hset($hashKey, $areaKey, $mark[0] + 1 . '-' . $mark[1]);
  153. return $isDeduction;
  154. }
  155. }
  156. //必扣计算
  157. if (($ratio[0] - $mark[0]) <= ($ratio[1] - $mark[1])) {
  158. $isDeduction = 1;
  159. } else {
  160. $isDeduction = mt_rand(0, 1);
  161. }
  162. if ($isDeduction == 1) {
  163. $mark[1] += 1;
  164. }
  165. $mark[0] += 1;
  166. Redis::hset($hashKey, $areaKey, $mark[0] . '-' . $mark[1]);
  167. return $isDeduction;
  168. }
  169. }