PayRechargeController.php 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811
  1. <?php
  2. namespace App\Http\Controllers\Game;
  3. use App\Facade\TableName;
  4. use App\Game\Services\OuroGameService;
  5. use App\Http\Controllers\Controller;
  6. use App\Http\helper\NumConfig;
  7. use App\Models\Order;
  8. use App\Services\OrderServices;
  9. use App\Utility\SetNXLock;
  10. use App\Util;
  11. use Illuminate\Http\Request;
  12. use Illuminate\Support\Facades\DB;
  13. use Illuminate\Support\Facades\Redis;
  14. class PayRechargeController extends Controller
  15. {
  16. // 充值记录
  17. public function orderList(Request $request)
  18. {
  19. $user_id = (int)$request->globalUser->UserID;//$request->get('user_id', 1);
  20. $page = $request->get('page', 1);
  21. $pageSize = $request->get('pageSize', 7);
  22. $redisKey = 'PayRecharge_orderList_'.$user_id;
  23. if (!SetNXLock::getExclusiveLock($redisKey)) {
  24. return apiReturnFail(['web.withdraw.try_again_later','Tente novamente mais tarde']);
  25. }
  26. $where[] = ['user_id', $user_id];
  27. $where[] = ['pay_status', 1];
  28. $cacheTime = 60 * rand(1, 2);
  29. // $list = cache()->remember($user_id . '_order_list', $cacheTime, function () use ($where, $pageSize) {
  30. //
  31. // return Order::where($where)
  32. // ->orderBy('finished_at', 'desc')
  33. // ->selectRaw('amount,payment_code,order_sn as payment_sn,finished_at,created_at,pay_status')
  34. // ->paginate(15,['*'],'page',1);
  35. // });
  36. $list = Order::query()->where($where)
  37. ->orderBy('finished_at', 'desc')
  38. ->selectRaw('amount,payment_code,order_sn as payment_sn,finished_at,created_at,pay_status,type')
  39. ->paginate($pageSize);
  40. // ->paginate(15,['*'],'page',1);
  41. foreach ($list as &$val) {
  42. $val->amount = number_format($val->amount, 2, '.', '');
  43. }
  44. SetNXLock::release($redisKey);
  45. return apiReturnSuc($list);
  46. }
  47. // 首充
  48. public function firstPay(Request $request)
  49. {
  50. $user = $request->user();
  51. $user_recharge = DB::table(TableName::QPAccountsDB() . 'YN_VIPAccount')
  52. ->where('UserID', $user->UserID)
  53. ->value('Recharge') ?: 0;
  54. if($user_recharge)return apiReturnSuc();
  55. $firstPayGift = DB::table('agent.dbo.recharge_gift')
  56. ->where('gift_id', 301)->first();
  57. if(!$firstPayGift) return apiReturnFail();
  58. $names = DB::table('agent.dbo.admin_configs')
  59. ->where([
  60. 'type' => 'pay_method',
  61. 'status' => 1,
  62. ])
  63. ->selectRaw('id, name, status, new_pay_type as type')
  64. ->orderByDesc('sort')->get()->toArray();
  65. $list = DB::table('agent.dbo.recharge_gear')
  66. ->select('id','money','favorable_price','give')
  67. ->orderBy('money', 'asc')->where('status', 1)->get();
  68. $vip = DB::table(TableName::QPAccountsDB() . 'YN_VIPAccount')
  69. ->where('UserID', $user->UserID)
  70. ->value('Recharge') ?: 0;
  71. $gear = Util::filterGearByDevice(\GuzzleHttp\json_encode($names), $vip);
  72. foreach ($list as &$val) {
  73. $val->favorable_price = $val->favorable_price + $val->give;
  74. $val->gear = $gear;
  75. $val->recommend = 0;
  76. if($val->money == $firstPayGift->recommend){
  77. $val->recommend = 1;
  78. }
  79. }
  80. return apiReturnSuc(compact('list', 'firstPayGift'));
  81. }
  82. // 首充礼包(带倒计时逻辑)
  83. public function firstPayGift(Request $request)
  84. {
  85. $user = $request->user();
  86. // 获取礼包配置
  87. $giftConfig = DB::table('agent.dbo.recharge_gift')
  88. ->where('gift_id', 301)
  89. ->first();
  90. if (!$giftConfig) {
  91. return apiReturnFail('礼包配置不存在');
  92. }
  93. // 检查用户是否购买了首充礼包
  94. $giftRecord = DB::table('agent.dbo.first_pay_gift_records')
  95. ->where('user_id', $user->UserID)
  96. ->first();
  97. // ========== 未购买礼包:返回充值列表 + 礼包配置 + 倒计时 ==========
  98. if (!$giftRecord) {
  99. // 获取充值档位列表
  100. $list = DB::table('agent.dbo.recharge_gear')
  101. ->select('money', 'favorable_price', 'give', 'gear')
  102. ->orderBy('money', 'asc')
  103. ->where('status', 1)
  104. ->where('in_shop', 1)
  105. ->get();
  106. $vip = DB::table(TableName::QPAccountsDB() . 'YN_VIPAccount')
  107. ->where('UserID', $user->UserID)
  108. ->value('Recharge') ?: 0;
  109. foreach ($list as &$val) {
  110. $val->favorable_price = $val->favorable_price + $val->give;
  111. $val->recommend = 0;
  112. if ($val->money == $giftConfig->recommend) {
  113. $val->recommend = 1;
  114. }
  115. if (!empty($val->gear)) {
  116. $val->gear = Util::filterGearByDevice($val->gear, $vip);
  117. }
  118. }
  119. // ========== 处理倒计时逻辑(仅未购买时) ==========
  120. $redisKey = "first_pay_gift_timer_{$user->UserID}";
  121. $currentTime = time();
  122. $timeLeft = 0;
  123. $timerData = Redis::get($redisKey);
  124. if ($timerData) {
  125. $timerData = json_decode($timerData, true);
  126. $firstRequestTime = $timerData['first_request_time'];
  127. $phase = $timerData['phase'];
  128. // 阶段1:valid_h倒计时
  129. if ($phase === 'first') {
  130. $expireTime = $firstRequestTime + ($giftConfig->valid_h * 3600);
  131. if ($currentTime >= $expireTime) {
  132. $expireDate = date('Y-m-d', $expireTime);
  133. $currentDate = date('Y-m-d', $currentTime);
  134. if ($expireDate !== $currentDate) {
  135. // 进入阶段2
  136. $nextDayStart = time();
  137. $newExpireTime = $nextDayStart + ($giftConfig->valid_h_2 * 3600);
  138. $newTimerData = [
  139. 'first_request_time' => $firstRequestTime,
  140. 'phase' => 'daily',
  141. 'current_cycle_start' => $nextDayStart,
  142. 'last_expire_time' => $newExpireTime
  143. ];
  144. Redis::set($redisKey, json_encode($newTimerData));
  145. $timeLeft = max(0, $newExpireTime - $currentTime);
  146. }
  147. } else {
  148. $timeLeft = $expireTime - $currentTime;
  149. }
  150. }
  151. // 阶段2:每日循环
  152. elseif ($phase === 'daily') {
  153. $currentCycleStart = $timerData['current_cycle_start'];
  154. $expireTime = $currentCycleStart + ($giftConfig->valid_h_2 * 3600);
  155. if ($currentTime >= $expireTime) {
  156. $expireDate = date('Y-m-d', $expireTime);
  157. $currentDate = date('Y-m-d', $currentTime);
  158. if ($expireDate !== $currentDate) {
  159. $todayStart = time();
  160. $newExpireTime = $todayStart + ($giftConfig->valid_h_2 * 3600);
  161. $newTimerData = [
  162. 'first_request_time' => $firstRequestTime,
  163. 'phase' => 'daily',
  164. 'current_cycle_start' => $todayStart,
  165. 'last_expire_time' => $newExpireTime
  166. ];
  167. Redis::set($redisKey, json_encode($newTimerData));
  168. $timeLeft = max(0, $newExpireTime - $currentTime);
  169. }
  170. } else {
  171. $timeLeft = $expireTime - $currentTime;
  172. }
  173. }
  174. } else {
  175. // 首次请求,初始化倒计时
  176. $expireTime = $currentTime + ($giftConfig->valid_h * 3600);
  177. $timerData = [
  178. 'first_request_time' => $currentTime,
  179. 'phase' => 'first',
  180. 'last_expire_time' => $expireTime
  181. ];
  182. Redis::set($redisKey, json_encode($timerData));
  183. $timeLeft = $giftConfig->valid_h * 3600;
  184. }
  185. return apiReturnSuc([
  186. 'has_purchased' => false, // 未购买标记
  187. 'list' => $list, // 充值档位列表
  188. 'gift_info' => [
  189. 'gift_id' => $giftConfig->gift_id,
  190. 'gift_name' => $giftConfig->gift_name,
  191. 'total_bonus' => $giftConfig->total_bonus,
  192. 'bonus_instantly' => $giftConfig->bonus_instantly,
  193. 'day_rewards' => $giftConfig->day_rewards ? json_decode($giftConfig->day_rewards) : null,
  194. 'betting_bonus' => $giftConfig->betting_bonus ? json_decode($giftConfig->betting_bonus) : null,
  195. 'betting_task' => $giftConfig->betting_task ? json_decode($giftConfig->betting_task) : null,
  196. ],
  197. 'time_left' => $timeLeft, // ✅ 倒计时(未购买时展示)
  198. 'expire_at' => time() + $timeLeft // ✅ 过期时间戳
  199. ]);
  200. }
  201. // ========== 已购买礼包:返回任务进度(无倒计时) ==========
  202. // 获取用户当前累计下注(从统计表)
  203. $userStats = DB::table('QPRecordDB.dbo.RecordUserTotalStatistics')
  204. ->where('UserID', $user->UserID)
  205. ->first();
  206. $currentTotalBet = $userStats->TotalBet ?? 0;
  207. // 更新下注进度到礼包记录
  208. DB::table('agent.dbo.first_pay_gift_records')
  209. ->where('user_id', $user->UserID)
  210. ->update([
  211. 'betting_current_bet' => $currentTotalBet / NumConfig::NUM_VALUE,
  212. 'updated_at' => date('Y-m-d H:i:s')
  213. ]);
  214. // 重新获取最新记录
  215. $giftRecord = DB::table('agent.dbo.first_pay_gift_records')
  216. ->where('user_id', $user->UserID)
  217. ->first();
  218. // 解析任务数据
  219. $dayRewardsData = $giftRecord->day_rewards_data ? json_decode($giftRecord->day_rewards_data, true) : null;
  220. $bettingBonusData = $giftRecord->betting_bonus_data ? json_decode($giftRecord->betting_bonus_data, true) : null;
  221. $bettingTaskData = $giftRecord->betting_task_data ? json_decode($giftRecord->betting_task_data, true) : null;
  222. // 构建返回数据
  223. $giftInfo = [
  224. 'gift_id' => $giftRecord->gift_id,
  225. 'gift_name' => $giftRecord->gift_name,
  226. 'total_bonus' => (float)$giftRecord->total_bonus,
  227. 'bonus_instantly' => (float)$giftRecord->bonus_instantly,
  228. 'pay_amount' => (float)$giftRecord->pay_amount,
  229. ];
  230. // 每日奖励进度
  231. if ($dayRewardsData) {
  232. // 计算当前是购买后的第几天
  233. $purchaseDate = date('Y-m-d', strtotime($giftRecord->created_at));
  234. $today = date('Y-m-d');
  235. $daysPassed = floor((strtotime($today) - strtotime($purchaseDate)) / 86400);
  236. $startDay = $dayRewardsData['start_day'] ?? 1;
  237. $bonusDay = $dayRewardsData['bonus_day'] ?? 0;
  238. $claimedDays = $giftRecord->day_rewards_claimed;
  239. // $startDay = $startDay-1;
  240. // 判断每日奖励状态
  241. // 0=不可领取, 1=可领取, 2=已领取, 3=过期
  242. $dayRewardStatus = 0; // 默认不可领取
  243. // 检查是否过期(购买后7天)
  244. if ($daysPassed >= 7) {
  245. $dayRewardStatus = 3; // 过期
  246. } elseif ($daysPassed >= $startDay-1) {
  247. // 计算今天是第几个奖励日(从起始天数开始)
  248. $rewardIndex = $daysPassed - ($startDay-1);
  249. if ($rewardIndex < $bonusDay) {
  250. // 在奖励期内
  251. if ($claimedDays > $rewardIndex) {
  252. $dayRewardStatus = 2; // 已领取
  253. } else {
  254. // 即便前几天漏领,后续奖励仍可继续领取(漏掉的视为作废)
  255. $dayRewardStatus = 1; // 可领取
  256. }
  257. } else {
  258. // 超过奖励天数
  259. $dayRewardStatus = 2; // 已领取完
  260. }
  261. }
  262. $giftInfo['day_rewards'] = [
  263. 'total_bonus' => (float)$giftRecord->day_rewards_total,
  264. 'bonus_day' => $bonusDay,
  265. 'start_day' => $startDay,
  266. 'bonus' => $dayRewardsData['bonus'] ?? [],
  267. 'claimed_days' => $claimedDays,
  268. 'progress' => $claimedDays . '/' . $bonusDay,
  269. 'status' => $dayRewardStatus, // 0=不可领取, 1=可领取, 2=已领取, 3=过期
  270. 'status_text' => ['不可领取', '可领取', '已领取', '过期'][$dayRewardStatus] ?? '未知'
  271. ];
  272. }
  273. // 下注奖励进度
  274. if ($bettingBonusData) {
  275. $perBet = $bettingBonusData['per_bet'] ?? 100; // 每次下注要求
  276. $perBetBonus = $bettingBonusData['per_bet_bonus'] ?? 2; // 每次奖励金额(不是百分比)
  277. $currentBet = $giftRecord->betting_current_bet; // 当前累计下注
  278. $totalBonusLimit = $giftRecord->betting_bonus_total; // 总奖励上限
  279. $claimedAmount = $giftRecord->betting_bonus_claimed; // 已领取金额
  280. $remainingBonus = $totalBonusLimit - $claimedAmount; // 剩余可领取金额
  281. // 每次可领取的金额(直接使用配置的值,不是百分比计算)
  282. $perReward = (float)$perBetBonus;
  283. // 根据当前下注计算已达成的次数
  284. $completedTimes = floor($currentBet / $perBet);
  285. // 已领取的次数
  286. $claimedTimes = $claimedAmount > 0 ? floor($claimedAmount / $perReward) : 0;
  287. // 当前可领取次数(但不能超过剩余总额)
  288. $canClaimTimes = $completedTimes - $claimedTimes;
  289. $maxCanClaimTimes = floor($remainingBonus / $perReward); // 剩余总额最多可领次数
  290. $canClaimTimes = min($canClaimTimes, $maxCanClaimTimes);
  291. // 当前可领取金额
  292. $canClaimAmount = min($canClaimTimes * $perReward, $remainingBonus);
  293. // 计算下次领取需要的下注金额
  294. $nextClaimBet = 0;
  295. if ($remainingBonus > 0 && $canClaimTimes == 0) {
  296. // 还有剩余奖励但当前不能领取,计算还需下注多少
  297. $nextClaimBet = ($claimedTimes + 1) * $perBet - $currentBet;
  298. }
  299. // 判断下注奖励状态
  300. // 0=不可领取(可领取金额为0), 1=可领取, 2=已领取(所有奖励都领完), 3=过期
  301. $bettingBonusStatus = 0; // 默认不可领取
  302. // 检查是否过期(购买后7天)
  303. if ($daysPassed >= 7) {
  304. $bettingBonusStatus = 3; // 过期
  305. } elseif ($remainingBonus <= 0) {
  306. $bettingBonusStatus = 2; // 已领取完
  307. } elseif ($canClaimAmount > 0) {
  308. $bettingBonusStatus = 1; // 可领取
  309. } else {
  310. $bettingBonusStatus = 0; // 不可领取(下注不足)
  311. }
  312. $giftInfo['betting_bonus'] = [
  313. 'total_bonus' => (float)$totalBonusLimit, // 总奖励上限
  314. 'per_bet' => $perBet, // 每次下注要求
  315. 'per_bet_bonus' => $perReward, // 每次奖励金额(实际金额)
  316. // 'per_reward' => $perReward, // 每次奖励金额(保持兼容)
  317. 'current_bet' => (float)$currentBet, // 当前累计下注
  318. 'claimed_amount' => (float)$claimedAmount, // 已领取金额
  319. 'remaining_bonus' => (float)$remainingBonus, // 剩余可领金额
  320. 'can_claim_amount' => (float)$canClaimAmount, // 当前可领取金额
  321. 'can_claim_times' => max(0, $canClaimTimes), // 当前可领取次数
  322. 'next_claim_bet' => max(0, $nextClaimBet), // 下次领取还需下注
  323. 'progress' => round($currentBet, 2) . '/' . round($claimedTimes * $perBet + $perBet, 2), // 当前进度/下次领取目标
  324. 'status' => $bettingBonusStatus, // 0=不可领取, 1=可领取, 2=已领取, 3=过期
  325. 'status_text' => ['不可领取', '可领取', '已领取', '过期'][$bettingBonusStatus] ?? '未知'
  326. ];
  327. }
  328. // 下注任务进度
  329. if ($bettingTaskData) {
  330. $betPayTimes = $bettingTaskData['bet_pay_times'] ?? 60;
  331. $requiredBet = $giftRecord->pay_amount * $betPayTimes;
  332. $currentProgress = $giftRecord->betting_current_bet;
  333. $taskCompleted = $currentProgress >= $requiredBet;
  334. $isClaimed = $giftRecord->betting_task_claimed == 1;
  335. // 判断下注任务状态
  336. // 0=不可领取, 1=可领取, 2=已领取, 3=过期
  337. $bettingTaskStatus = 0; // 默认不可领取
  338. // 检查是否过期(购买后7天)
  339. if ($daysPassed >= 7) {
  340. $bettingTaskStatus = 3; // 过期
  341. } elseif ($isClaimed) {
  342. $bettingTaskStatus = 2; // 已领取
  343. } elseif ($taskCompleted) {
  344. $bettingTaskStatus = 1; // 可领取(任务完成且未领取)
  345. } else {
  346. $bettingTaskStatus = 0; // 不可领取(任务未完成)
  347. }
  348. $giftInfo['betting_task'] = [
  349. 'total_bonus' => (float)$giftRecord->betting_task_total,
  350. 'bet_pay_times' => $betPayTimes,
  351. 'required_bet' => $requiredBet, // 需要下注的金额
  352. 'current_bet' => (float)$currentProgress, // 当前累计下注
  353. 'progress' => round($currentProgress, 2) . '/' . $requiredBet,
  354. 'status' => $bettingTaskStatus, // 0=不可领取, 1=可领取, 2=已领取, 3=过期
  355. 'status_text' => ['不可领取', '可领取', '已领取', '过期'][$bettingTaskStatus] ?? '未知'
  356. ];
  357. }
  358. $giftInfo['expired'] = strtotime($giftRecord->created_at)+86400*7;
  359. return apiReturnSuc([
  360. 'has_purchased' => true, // 已购买标记
  361. 'gift_info' => $giftInfo
  362. // ✅ 已购买用户不返回倒计时
  363. ]);
  364. }
  365. /**
  366. * 领取首充礼包奖励
  367. */
  368. public function claimFirstPayGiftReward(Request $request)
  369. {
  370. $user = $request->user();
  371. $userId = $user->UserID;
  372. $rewardType = $request->input('reward_type'); // 'day_reward', 'betting_bonus', 'betting_task'
  373. // 获取礼包记录
  374. $giftRecord = DB::table('agent.dbo.first_pay_gift_records')
  375. ->where('user_id', $userId)
  376. ->first();
  377. if (!$giftRecord) {
  378. return apiReturnFail('未购买首充礼包');
  379. }
  380. $rewardAmount = 0;
  381. try {
  382. // 每日奖励领取
  383. if ($rewardType === 'day_reward') {
  384. $dayRewardsData = json_decode($giftRecord->day_rewards_data, true);
  385. if (!$dayRewardsData) {
  386. return apiReturnFail('没有每日奖励配置');
  387. }
  388. $bonusDay = $dayRewardsData['bonus_day'] ?? 0;
  389. $startDay = $dayRewardsData['start_day'] ?? 1;
  390. $bonusArray = $dayRewardsData['bonus'] ?? [];
  391. $claimedDays = $giftRecord->day_rewards_claimed;
  392. // 检查是否还有可领取的天数
  393. if ($claimedDays >= $bonusDay) {
  394. return apiReturnFail('每日奖励已全部领取');
  395. }
  396. // 计算当前是购买后的第几天
  397. $purchaseDate = date('Y-m-d', strtotime($giftRecord->created_at));
  398. $currentDate = date('Y-m-d');
  399. $daysPassed = floor((strtotime($currentDate) - strtotime($purchaseDate)) / 86400);
  400. // 检查是否到了可以领取的天数(从第start_day天开始)
  401. if ($daysPassed < $startDay-1) {
  402. return apiReturnFail('还未到可领取时间,需要从第' . $startDay . '天开始');
  403. }
  404. // 计算今天应该领取第几天的奖励
  405. // 例如:start_day=2,今天是第3天,应该领取第1个奖励(索引0)
  406. $todayRewardIndex = $daysPassed - ($startDay-1);
  407. // 检查是否超过奖励天数
  408. if ($todayRewardIndex >= $bonusDay) {
  409. return apiReturnFail('每日奖励已过期');
  410. }
  411. // 检查今天是否已领取
  412. $lastClaimDate = $giftRecord->day_last_claim_date;
  413. if ($lastClaimDate && $lastClaimDate === $currentDate) {
  414. return apiReturnFail('今天已经领取过了');
  415. }
  416. // 检查是否跳过了某些天(过期不补领)
  417. // 如果今天应该领第5天的奖励,但用户只领了3天,那就直接领第5天的
  418. if ($todayRewardIndex > $claimedDays) {
  419. // 跳过了一些天,更新已领取天数为今天的索引
  420. $claimedDays = $todayRewardIndex;
  421. }
  422. // 计算今天可领取的奖励(使用todayRewardIndex作为索引)
  423. $todayBonusPercent = $bonusArray[$todayRewardIndex] ?? 0;
  424. $rewardAmount = round($giftRecord->pay_amount * $todayBonusPercent / 100, 2);
  425. // 更新记录
  426. DB::table('agent.dbo.first_pay_gift_records')
  427. ->where('user_id', $userId)
  428. ->update([
  429. 'day_rewards_claimed' => $todayRewardIndex + 1, // 已领取到第几天(索引+1)
  430. 'day_last_claim_date' => $currentDate,
  431. 'updated_at' => date('Y-m-d H:i:s')
  432. ]);
  433. }
  434. // 下注奖励领取
  435. elseif ($rewardType === 'betting_bonus') {
  436. $bettingBonusData = json_decode($giftRecord->betting_bonus_data, true);
  437. if (!$bettingBonusData) {
  438. return apiReturnFail('没有下注奖励配置');
  439. }
  440. $perBet = $bettingBonusData['per_bet'] ?? 100; // 每次下注要求
  441. $perBetBonus = $bettingBonusData['per_bet_bonus'] ?? 2; // 每次奖励金额(不是百分比)
  442. $currentBet = $giftRecord->betting_current_bet; // 当前累计下注
  443. $totalBonusLimit = $giftRecord->betting_bonus_total; // 总奖励上限
  444. $claimedAmount = $giftRecord->betting_bonus_claimed; // 已领取金额
  445. $remainingBonus = $totalBonusLimit - $claimedAmount; // 剩余可领金额
  446. // 检查是否还有剩余奖励
  447. if ($remainingBonus <= 0) {
  448. return apiReturnFail('下注奖励已全部领取');
  449. }
  450. // 每次可领取的金额(直接使用配置的值,不是百分比计算)
  451. $perReward = (float)$perBetBonus;
  452. // 根据当前下注计算已达成的次数
  453. $completedTimes = floor($currentBet / $perBet);
  454. // 已领取的次数
  455. $claimedTimes = $claimedAmount > 0 ? floor($claimedAmount / $perReward) : 0;
  456. // 可领取次数(下注达成的次数 - 已领取次数)
  457. $canClaimTimes = $completedTimes - $claimedTimes;
  458. // 检查是否可以领取
  459. if ($canClaimTimes <= 0) {
  460. return apiReturnFail('下注金额不足,还需下注 ' . (($claimedTimes + 1) * $perBet - $currentBet) . ' 才能领取');
  461. }
  462. // ✅ 一次性领取所有已达成的奖励(但不能超过剩余总额)
  463. $totalCanClaimAmount = $canClaimTimes * $perReward; // 理论可领取总额
  464. $rewardAmount = min($totalCanClaimAmount, $remainingBonus); // 实际领取金额(不超过剩余总额)
  465. $actualClaimTimes = floor($rewardAmount / $perReward); // 实际领取次数
  466. // 更新记录
  467. DB::table('agent.dbo.first_pay_gift_records')
  468. ->where('user_id', $userId)
  469. ->update([
  470. 'betting_bonus_claimed' => $giftRecord->betting_bonus_claimed + $rewardAmount,
  471. 'updated_at' => date('Y-m-d H:i:s')
  472. ]);
  473. \Log::info('下注奖励领取', [
  474. 'user_id' => $userId,
  475. 'can_claim_times' => $canClaimTimes,
  476. 'actual_claim_times' => $actualClaimTimes,
  477. 'reward_amount' => $rewardAmount
  478. ]);
  479. }
  480. // 下注任务领取
  481. elseif ($rewardType === 'betting_task') {
  482. if ($giftRecord->betting_task_claimed == 1) {
  483. return apiReturnFail('下注任务奖励已领取');
  484. }
  485. $bettingTaskData = json_decode($giftRecord->betting_task_data, true);
  486. if (!$bettingTaskData) {
  487. return apiReturnFail('没有下注任务配置');
  488. }
  489. $betPayTimes = $bettingTaskData['bet_pay_times'] ?? 60;
  490. $requiredBet = $giftRecord->pay_amount * $betPayTimes;
  491. $currentBet = $giftRecord->betting_current_bet;
  492. if ($currentBet < $requiredBet) {
  493. return apiReturnFail('下注金额不足,需要下注 ' . $requiredBet);
  494. }
  495. $rewardAmount = $giftRecord->betting_task_total;
  496. // 更新记录
  497. DB::table('agent.dbo.first_pay_gift_records')
  498. ->where('user_id', $userId)
  499. ->update([
  500. 'betting_task_claimed' => 1,
  501. 'updated_at' => date('Y-m-d H:i:s')
  502. ]);
  503. }
  504. else {
  505. return apiReturnFail('无效的奖励类型');
  506. }
  507. // 添加奖励到用户账户
  508. if ($rewardAmount > 0) {
  509. OuroGameService::AddScore($userId, $rewardAmount * NumConfig::NUM_VALUE, 52, true); // 52=首充礼包奖励
  510. \Log::info('首充礼包奖励领取', [
  511. 'user_id' => $userId,
  512. 'reward_type' => $rewardType,
  513. 'amount' => $rewardAmount
  514. ]);
  515. }
  516. return apiReturnSuc([
  517. 'amount' => $rewardAmount,
  518. 'message' => '成功领取 ' . $rewardAmount . ' 奖励'
  519. ]);
  520. } catch (\Exception $e) {
  521. \Log::error('首充礼包奖励领取失败', [
  522. 'user_id' => $userId,
  523. 'error' => $e->getMessage()
  524. ]);
  525. return apiReturnFail('领取失败:' . $e->getMessage());
  526. }
  527. }
  528. /**
  529. * 获取首充礼包数据(包含充值档位列表)
  530. * @param $firstPayGift 礼包配置
  531. * @param $timeLeft 剩余秒数(已经是用户实际剩余时间)
  532. */
  533. private function getFirstPayGiftData($firstPayGift, $timeLeft)
  534. {
  535. // 获取支付方式
  536. // $names = DB::table('agent.dbo.admin_configs')
  537. // ->where([
  538. // 'type' => 'pay_method',
  539. // 'status' => 1,
  540. // ])
  541. // ->selectRaw('id, name, status, new_pay_type as type')
  542. // ->orderByDesc('sort')
  543. // ->get()
  544. // ->toArray();
  545. // 获取充值档位
  546. $list = DB::table('agent.dbo.recharge_gear')
  547. ->select('money', 'favorable_price', 'give','gear')
  548. ->orderBy('money', 'asc')
  549. ->where('status', 1)
  550. ->where('in_shop', 1)
  551. ->get();
  552. // $gear = \GuzzleHttp\json_encode($names);
  553. // 注意:getFirstPayGiftData 方法需要接收 $userId 参数才能获取 $vip
  554. // 这里暂时使用 0,因为该方法没有 $userId 参数
  555. $vip = 0;
  556. foreach ($list as &$val) {
  557. $val->favorable_price = $val->favorable_price + $val->give;
  558. // $val->gear = $gear;
  559. $val->recommend = 0;
  560. if ($val->money == $firstPayGift->recommend) {
  561. $val->recommend = 1;
  562. }
  563. if (!empty($val->gear)) {
  564. $val->gear = Util::filterGearByDevice($val->gear, $vip);
  565. }
  566. }
  567. return apiReturnSuc([
  568. 'list' => $list,
  569. 'gift_info' => [
  570. 'gift_id' => $firstPayGift->gift_id,
  571. 'gift_name' => $firstPayGift->gift_name,
  572. 'total_bonus' => $firstPayGift->total_bonus,
  573. 'bonus_instantly' => $firstPayGift->bonus_instantly,
  574. 'day_rewards' => $firstPayGift->day_rewards?json_decode($firstPayGift->day_rewards):'',
  575. 'betting_bonus' => $firstPayGift->betting_bonus?json_decode($firstPayGift->betting_bonus):'',
  576. 'betting_task' => $firstPayGift->betting_task?json_decode($firstPayGift->betting_task):'',
  577. ],
  578. 'time_left' => $timeLeft, // 剩余秒数
  579. 'expire_at' => time() + $timeLeft // 过期时间戳
  580. ]);
  581. }
  582. public function firstPayMulti(Request $request)
  583. {
  584. $user = LoginController::checkLogin($request);
  585. if($user){
  586. if(env('CONFIG_24680_NFTD_99',0)==0)if($user->Channel==99)return apiReturnFail();
  587. $fpkey='Firstpay_'.$user->UserID;
  588. if(Redis::exists($fpkey)){
  589. $data=Redis::get($fpkey);
  590. $data=json_decode($data,true);
  591. $data['timeleft']=86400-(time()-$data['buytime']);
  592. return apiReturnSuc(['leftitem'=>$data]);
  593. }
  594. $user_recharge = DB::table(TableName::QPAccountsDB() . 'YN_VIPAccount')
  595. ->where('UserID', $user->UserID)
  596. ->value('Recharge') ?: 0;
  597. if($user_recharge)return apiReturnFail();
  598. }
  599. $items=DB::table('agent.dbo.recharge_gear')
  600. ->where('status',1)
  601. ->where('second_give','>',0)
  602. ->where('first_pay','>=', 1)
  603. ->select('gift_id','money','give','favorable_price','second_give')->get()->each(function($item){
  604. $item->id=28;
  605. })->toArray();
  606. $default=count($items)-1;
  607. return apiReturnSuc(compact('items','default'));
  608. }
  609. // 破产礼包
  610. public function bankruptcyGift(Request $request)
  611. {
  612. $user = $request->user();
  613. // 判断用户是否充值
  614. $user_recharge = DB::table(TableName::QPAccountsDB() . 'YN_VIPAccount')
  615. ->where('UserID', $user->UserID)
  616. ->value('Recharge') ?: 0;
  617. if ($user_recharge <= 0) {
  618. return apiReturnFail('用户未充值');
  619. }
  620. // 获取所有破产礼包配置 (gift_id=302)
  621. $bankruptcyGifts = DB::table('agent.dbo.recharge_gift')
  622. ->where('gift_id', 302)
  623. ->get();
  624. if ($bankruptcyGifts->isEmpty()) {
  625. return apiReturnFail('破产礼包配置不存在');
  626. }
  627. $result = [];
  628. // 遍历每条礼包配置,根据 recommend 关联 recharge_gear
  629. foreach ($bankruptcyGifts as $gift) {
  630. $gear = DB::table('agent.dbo.recharge_gear')
  631. ->select('money', 'favorable_price', 'gear')
  632. ->where('money', $gift->recommend)
  633. ->where('status', 1)
  634. ->first();
  635. if ($gear) {
  636. $gear->gift_id = $gift->gift_id;
  637. $gear->total_bonus = $gift->total_bonus;
  638. $gear->bonus = $gift->total_bonus - 100;
  639. if (!empty($gear->gear)) {
  640. $vip = DB::table(TableName::QPAccountsDB() . 'YN_VIPAccount')
  641. ->where('UserID', $user->UserID)
  642. ->value('Recharge') ?: 0;
  643. $gear->gear = Util::filterGearByDevice($gear->gear, $vip);
  644. }
  645. $result[] = $gear;
  646. }
  647. }
  648. // 按 money 排序
  649. usort($result, function($a, $b) {
  650. return $a->money <=> $b->money;
  651. });
  652. return apiReturnSuc($result);
  653. }
  654. public function getSecondGive(Request $request)
  655. {
  656. $user = $request->user();
  657. $fpkey='Firstpay_'.$user->UserID;
  658. if(Redis::exists($fpkey)){
  659. $data=Redis::get($fpkey);
  660. $data=json_decode($data,true);
  661. $data['timeleft']=86400-(time()-$data['buytime']);
  662. if($data['timeleft']<=0) {
  663. Redis::del($fpkey);
  664. //加钱
  665. if($data['second_give']){
  666. $czReason=$data['czReason'];
  667. $cjReason=$data['cjReason'];
  668. [$OrgScore,$NowScore]=OuroGameService::AddScore($user->UserID,$data['second_give']*NumConfig::NUM_VALUE,$cjReason);
  669. //更新二次领钱记录
  670. DB::table(TableName::agent() . 'guide_payment')->where('UserID',$user->UserID)->update([
  671. 'GetSecondTime' => now(),
  672. 'SecondScoreNum'=>$data['second_give']*NumConfig::NUM_VALUE
  673. ]);
  674. return apiReturnSuc(compact('OrgScore','NowScore'));
  675. }
  676. return apiReturnSuc();
  677. }
  678. }
  679. return apiReturnFail(['web.withdraw.try_again_later','Tente novamente mais tarde']);
  680. }
  681. }