Award.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. <?php
  2. /**
  3. * 奖励服务模块
  4. * @author wesmiler
  5. */
  6. namespace app\weixin\service;
  7. use app\weixin\model\AccountLog;
  8. use app\weixin\model\Market;
  9. use app\weixin\model\Member;
  10. use app\weixin\model\UserBalanceLog;
  11. use app\weixin\model\Wechat;
  12. use think\Db;
  13. class Award
  14. {
  15. /**
  16. * 分享邀请用户奖励结算
  17. * @param $userId
  18. * @param array $regUserInfo
  19. * @return array|false
  20. * @throws \think\Exception
  21. * @throws \think\db\exception\DataNotFoundException
  22. * @throws \think\db\exception\ModelNotFoundException
  23. * @throws \think\exception\DbException
  24. * @throws \think\exception\PDOException
  25. */
  26. public static function inviteUser($userId, $regUserInfo = [])
  27. {
  28. $userInfo = Member::where(['id' => $userId, 'user_status' => 1])
  29. ->field('id,user_login,user_nickname,openid,redheart')
  30. ->find();
  31. $inviteOpenid = isset($userInfo['openid']) ? $userInfo['openid'] : '';
  32. $inviteNickname = isset($userInfo['user_nickname']) ? $userInfo['user_nickname'] : '';
  33. $redheart = isset($userInfo['redheart']) ? floatval($userInfo['redheart']) : 0;
  34. if (empty($userInfo)) {
  35. return false;
  36. }
  37. $siteInfo = cmf_get_site_info();
  38. $awardNum = isset($siteInfo['invite_award_redheart']) ? intval($siteInfo['invite_award_redheart']) : 0;
  39. if ($awardNum > 0) {
  40. // 奖励入账
  41. Member::where(['id' => $userId])->update(['redheart' => moneyFormat($redheart + $awardNum), 'updated_at' => date('Y-m-d H:i:s')]);
  42. // 账户明细
  43. $dateTime = date('Y-m-d H:i:s');
  44. $regNickname = isset($regUserInfo['user_nickname']) ? $regUserInfo['user_nickname'] : '';
  45. $regUserId = isset($regUserInfo['id']) ? $regUserInfo['id'] : '';
  46. $logData = [
  47. 'user_id' => $userId,
  48. 'type' => 4,
  49. 'account_type' => 1,
  50. 'change_type' => 1,
  51. 'money' => $awardNum,
  52. 'balance' => $redheart,
  53. 'remark' => "邀请用户[$regUserId],昵称[{$regNickname}]完成注册奖励",
  54. 'created_at' => $dateTime,
  55. ];
  56. db('account_log')->insertGetId($logData);
  57. // 推送消息
  58. $message = [];
  59. $pushInvite = isset($siteInfo['push_invite']) ? $siteInfo['push_invite'] : true;
  60. if ($inviteOpenid && $pushInvite) {
  61. $siteName = isset($siteInfo['site_name']) ? $siteInfo['site_name'] : '本公众号';
  62. $inviteMsg = isset($siteInfo['invite_msg']) ? $siteInfo['invite_msg'] : '';
  63. $match = ['{nickname}', '{inviteNickname}', '{awardNum}', '{datetime}', '{date}'];
  64. $data = [$regNickname, $inviteNickname, $awardNum, $dateTime, date('Y.m.d')];
  65. $inviteMsg = $inviteMsg ? str_replace($match, $data, $inviteMsg) : "尊敬的【{$inviteNickname}】,您在{$dateTime}成功邀请了用户{$regNickname}关注{$siteName},获得奖励{$awardNum}颗爱心!!!";
  66. $message = ['content' => $inviteMsg];
  67. }
  68. return ['openid' => $inviteOpenid, 'message' => $message];
  69. }
  70. return false;
  71. }
  72. /**
  73. * 分销收益奖励结算
  74. * @param $userId 当前奖励用户ID
  75. * @param $sourceUid 当前收益直接来源用户ID
  76. * @param $type 收益类型:对应market表ID
  77. * @param int $money 结算金额:比例分成必传金额
  78. * @return bool
  79. * @throws \think\Exception
  80. * @throws \think\db\exception\DataNotFoundException
  81. * @throws \think\db\exception\ModelNotFoundException
  82. * @throws \think\exception\DbException
  83. */
  84. public static function marketAward($userId, $sourceUid, $type, $money=0)
  85. {
  86. if (empty($type) || $userId <= 0 || ($userId == $sourceUid)) {
  87. return false;
  88. }
  89. // 分销参数配置
  90. $cacheKey = "market:award:u_{$userId}_{$sourceUid}_{$type}";
  91. $logData = ['money' => $money, 'sourceUid' => $sourceUid, 'userId'=> $userId];
  92. $marketConfig = Market::where(['id' => $type, 'status' => 1])->find();
  93. $marketType = isset($marketConfig['type']) ? $marketConfig['type'] : 2;
  94. $logData['config'] = $marketConfig;
  95. if (empty($marketConfig)) {
  96. PRedis::set("{$cacheKey}:error_config", $logData, 7200);
  97. return false;
  98. }
  99. // 验证上级用户是否符合奖励条件
  100. $where = ['id' => $userId, 'agent_type' => 1, 'agent_status' => 1];
  101. $field = 'id,openid,user_nickname,parent_id,user_login,balance,create_time';
  102. $userInfo = Member::getInfo($where, $field);
  103. $nickname = isset($userInfo['user_nickname']) ? trim($userInfo['user_nickname']) : '';
  104. $userLogin = isset($userInfo['user_login']) ? trim($userInfo['user_login']) : '';
  105. $balance = isset($userInfo['balance']) ? floatval($userInfo['balance']) : 0;
  106. $nickname = $nickname? $nickname : formatName($userLogin);
  107. $logData['userInfo'] = $userInfo;
  108. if (empty($userInfo)) {
  109. PRedis::set("{$cacheKey}:error_user", $logData, 7200);
  110. return false;
  111. }
  112. // 收益原始来源用户
  113. $sWhere = ['id' => $sourceUid, 'user_type' => 2];
  114. $sourceInfo = Member::getInfo($sWhere, $field);
  115. $sourceNickname = isset($sourceInfo['user_nickname']) ? $sourceInfo['user_nickname'] : '';
  116. $userLogin = isset($sourceInfo['user_login']) ? trim($sourceInfo['user_login']) : '';
  117. $sourceNickname = $sourceNickname? $sourceNickname : formatName($userLogin);
  118. // 旧用户不结算
  119. $createTime = isset($sourceInfo['create_time'])? $sourceInfo['create_time'] : 0;
  120. if ($createTime && $createTime <= strtotime('2021-02-23')) {
  121. PRedis::set("{$cacheKey}:error_user_reg_time", $logData, 7200);
  122. return false;
  123. }
  124. // 一级分销收益结算
  125. $logData['level'] = 1;
  126. $level1Award = isset($marketConfig['level_1']) ? floatval($marketConfig['level_1']) : 0;
  127. $awardMoney = $marketType==1? moneyFormat($level1Award) : moneyFormat($money * ($level1Award / 100),3);
  128. $logData['levelAward'] = $level1Award;
  129. $typeNames = [4=>'完善资料',5=>'完成身份认证',6=>'完成学历认证',7=>'完成工作认证',9=>'报名参加活动'];
  130. $typeName = isset($typeNames[$type])? $typeNames[$type] : ($money? "支付{$money}元,": '消费');
  131. if ($level1Award > 0 && $level1Award <= 100 && $awardMoney > 0) {
  132. // 账户变动
  133. Db::startTrans();
  134. if (Member::where($where)->setInc('balance', $awardMoney)) {
  135. // 写入奖励日志
  136. $levelName = "您邀请的[{$sourceNickname}]用户";
  137. $marketName = isset($marketConfig['name']) ? $marketConfig['name'] : '分销收益';
  138. $logTitle = "{$levelName}{$typeName},获得{$marketName}{$awardMoney}元";
  139. $log = [
  140. 'change' => $awardMoney,
  141. 'type' => $type,
  142. 'level' => 1,
  143. 'change_type' => 1,
  144. 'pay_money' => $awardMoney,
  145. 'user_id' => $userId,
  146. 'source_uid' => $sourceUid,
  147. 'balance' => moneyFormat($balance + $awardMoney),
  148. 'description' => $logTitle,
  149. 'create_time' => time(),
  150. 'status' => 1,
  151. ];
  152. $logData['log'] = $log;
  153. PRedis::set("{$cacheKey}:log", $logData, 7200);
  154. if(UserBalanceLog::insertGetId($log)){
  155. // 账户明细
  156. $accountData = [
  157. 'type' => 4,
  158. 'account_type' => 2,
  159. 'change_type' => 1,
  160. 'user_id' => $userId,
  161. 'money' => $awardMoney,
  162. 'balance' => $balance,
  163. 'created_at' => date('Y-m-d H:i:s'),
  164. 'remark' => $logTitle,
  165. ];
  166. if(AccountLog::insertGetId($accountData)){
  167. // 发送模板消息
  168. $openid = isset($userInfo['openid'])? $userInfo['openid'] : '';
  169. if($openid){
  170. $checkTime = date('Y.m.d H:i');
  171. $remark = "感谢您对拾光的信任,我们一起解救单身青年!点击查看收益明细";
  172. $msgParams = [
  173. 'title' => "您邀请的用户[$sourceNickname]{$typeName}所得的收益已到账!\n\n结算类型:\t{$marketName}",
  174. 'remark' => $remark,
  175. 'type' => 'income',
  176. 'keywords' => [
  177. 'keyword1' => [
  178. 'value' => "{$awardMoney}",
  179. 'color' => '#173177',
  180. ],
  181. 'keyword2' => [
  182. 'value' => $checkTime,
  183. 'color' => '#173177',
  184. ],
  185. ],
  186. 'url' => url('/weixin/market/income', '', '', true),
  187. ];
  188. PRedis::set("{$cacheKey}:message", ['result' => $userInfo, 'params' => $msgParams], 600);
  189. Wechat::sendTplMsg($openid, $msgParams);
  190. }
  191. Db::commit();;
  192. }else{
  193. PRedis::set("{$cacheKey}:account_log", $logData, 7200);
  194. Db::rollback();
  195. }
  196. }else{
  197. PRedis::set("{$cacheKey}:balance_log", $logData, 7200);
  198. Db::rollback();
  199. }
  200. } else {
  201. PRedis::set("{$cacheKey}:update_balance", $logData, 7200);
  202. Db::rollback();
  203. }
  204. } else {
  205. PRedis::set("{$cacheKey}:error_awardMoney", $logData, 7200);
  206. }
  207. // 二级分销收益结算
  208. $logData['level'] = 2;
  209. $userTwoId = isset($userInfo['parent_id'])? intval($userInfo['parent_id']) : 0;
  210. $cacheKey = "market:award:u_{$userTwoId}_{$sourceUid}_{$type}";
  211. if($userTwoId<=0 || $userTwoId == $userId || $userTwoId == $sourceUid){
  212. PRedis::set("{$cacheKey}:market2", $logData, 7200);
  213. return false;
  214. }
  215. $whereTwo = ['id' => $userTwoId, 'agent_type' => 1, 'agent_status' => 1];
  216. $userInfoTwo = Member::getInfo($whereTwo, $field);
  217. $balanceTwo = isset($userInfoTwo['balance']) ? floatval($userInfoTwo['balance']) : 0;
  218. $logData['userInfo'] = $userInfoTwo;
  219. if(empty($userInfoTwo)){
  220. PRedis::set("{$cacheKey}:error_userTwo", $logData, 7200);
  221. return false;
  222. }
  223. $level2Award = isset($marketConfig['level_2']) ? floatval($marketConfig['level_2']) : 0;
  224. $awardMoneyTwo = $marketType==1? moneyFormat($level2Award) : moneyFormat($money * ($level2Award / 100));
  225. $logData['levelAward'] = $level2Award;
  226. if ($level2Award > 0 && $level2Award <= 100 && $awardMoneyTwo > 0) {
  227. // 账户变动
  228. Db::startTrans();
  229. if (Member::where($whereTwo)->setInc('balance', $awardMoneyTwo)) {
  230. // 写入奖励日志
  231. $levelName = "您的下级[{$nickname}:]邀请的[{$sourceNickname}]用户";
  232. $marketName = isset($marketConfig['name']) ? $marketConfig['name'] : '分销收益';
  233. $logTitle = "{$levelName}{$typeName},获得{$marketName}{$awardMoneyTwo}元";
  234. $log = [
  235. 'change' => $awardMoneyTwo,
  236. 'type' => $type,
  237. 'level' => 2,
  238. 'change_type' => 1,
  239. 'pay_money' => $awardMoneyTwo,
  240. 'user_id' => $userTwoId,
  241. 'source_uid' => $userId,
  242. 'balance' => moneyFormat($balanceTwo + $awardMoneyTwo),
  243. 'description' => $logTitle,
  244. 'create_time' => time(),
  245. 'status' => 1,
  246. ];
  247. $logData['log'] = $log;
  248. PRedis::set("{$cacheKey}:log", $logData, 7200);
  249. if(UserBalanceLog::insertGetId($log)){
  250. // 账户明细
  251. $accountData = [
  252. 'type' => 4,
  253. 'account_type' => 2,
  254. 'change_type' => 1,
  255. 'user_id' => $userTwoId,
  256. 'money' => $awardMoneyTwo,
  257. 'balance' => $balanceTwo,
  258. 'created_at' => date('Y-m-d H:i:s'),
  259. 'remark' => $logTitle,
  260. ];
  261. if(AccountLog::insertGetId($accountData)){
  262. // 发送模板消息
  263. $openid = isset($userInfoTwo['openid'])? $userInfoTwo['openid'] : '';
  264. if($openid){
  265. $checkTime = date('Y.m.d H:i');
  266. $remark = "感谢您对拾光的信任,我们一起解救单身青年!点击查看收益明细";
  267. $msgParams = [
  268. 'title' => "您的下级[$nickname]邀请的用户[{$sourceNickname}]{$typeName}所得的收益已到账!\n\n结算类型:\t{$marketName}",
  269. 'remark' => $remark,
  270. 'type' => 'income',
  271. 'keywords' => [
  272. 'keyword1' => [
  273. 'value' => "{$awardMoneyTwo}",
  274. 'color' => '#173177',
  275. ],
  276. 'keyword2' => [
  277. 'value' => $checkTime,
  278. 'color' => '#173177',
  279. ],
  280. ],
  281. 'url' => url('/weixin/market/income', '', '', true),
  282. ];
  283. PRedis::set("{$cacheKey}:message", ['result' => $userInfoTwo, 'params' => $msgParams], 600);
  284. Wechat::sendTplMsg($openid, $msgParams);
  285. }
  286. Db::commit();
  287. }else{
  288. PRedis::set("{$cacheKey}:account_log", $logData, 7200);
  289. Db::rollback();
  290. return false;
  291. }
  292. }else{
  293. PRedis::set("{$cacheKey}:balance_log", $logData, 7200);
  294. Db::rollback();
  295. return false;
  296. }
  297. } else {
  298. PRedis::set("{$cacheKey}:update_balance", $logData, 7200);
  299. Db::rollback();
  300. return false;
  301. }
  302. } else {
  303. PRedis::set("{$cacheKey}:error_awardMoney", $logData, 7200);
  304. return false;
  305. }
  306. return true;
  307. }
  308. }