diff --git a/server/app/api/controller/GameController.php b/server/app/api/controller/GameController.php new file mode 100644 index 0000000..7875d50 --- /dev/null +++ b/server/app/api/controller/GameController.php @@ -0,0 +1,67 @@ +header('user-token'); + if (empty($token)) { + $auth = $request->header('authorization'); + if ($auth && stripos($auth, 'Bearer ') === 0) { + $token = trim(substr($auth, 7)); + } + } + if (empty($token)) { + return $this->fail('请携带 user-token'); + } + $userId = UserLogic::getUserIdFromToken($token); + if ($userId === null) { + return $this->fail('user-token 无效或已过期'); + } + + $count = (int) $request->post('count', 0); + if (!in_array($count, [1, 5, 10], true)) { + return $this->fail('购买抽奖券错误'); + } + + try { + $logic = new GameLogic(); + $data = $logic->buyLotteryTickets($userId, $count); + return $this->success($data); + } catch (\plugin\saiadmin\exception\ApiException $e) { + return $this->fail($e->getMessage()); + } + } + + /** + * 获取彩金池(中奖配置表) + * GET /api/game/lotteryPool + * header: auth-token + * 返回 DiceRewardConfig 列表(彩金池/中奖配置) + */ + public function lotteryPool(Request $request): Response + { + $list = DiceRewardConfig::order('id', 'asc')->select()->toArray(); + return $this->success($list); + } +} diff --git a/server/app/api/logic/GameLogic.php b/server/app/api/logic/GameLogic.php new file mode 100644 index 0000000..a9082aa --- /dev/null +++ b/server/app/api/logic/GameLogic.php @@ -0,0 +1,101 @@ + [消耗coin, 购买次数paid, 赠送次数free] + * 仅支持 1、5、10 档 + */ +class GameLogic +{ + public const PACKAGES = [ + 1 => ['coin' => 100, 'paid' => 1, 'free' => 0], // 1次/100coin + 5 => ['coin' => 500, 'paid' => 5, 'free' => 1], // 5张/500coin(5购买+1赠送,共6次) + 10 => ['coin' => 1000, 'paid' => 10, 'free' => 3], // 10张/1000coin(10购买+3赠送,共13次) + ]; + + /** 钱包流水类型:购买抽奖次数 */ + public const WALLET_TYPE_BUY_DRAW = 2; + + /** + * 购买抽奖券 + * @param int $playerId 玩家ID(即 user_id) + * @param int $count 购买档位:1 / 5 / 10 + * @return array 更新后的 coin, total_draw_count, paid_draw_count, free_draw_count + */ + public function buyLotteryTickets(int $playerId, int $count): array + { + if (!isset(self::PACKAGES[$count])) { + throw new ApiException('购买抽奖券错误'); + } + $pack = self::PACKAGES[$count]; + $cost = $pack['coin']; + $addPaid = $pack['paid']; + $addFree = $pack['free']; + $addTotal = $addPaid + $addFree; + + $player = DicePlayer::find($playerId); + if (!$player) { + throw new ApiException('用户不存在'); + } + $coinBefore = (float) $player->coin; + if ($coinBefore < $cost) { + throw new ApiException('平台币不足'); + } + + $coinAfter = $coinBefore - $cost; + $totalBefore = (int) ($player->total_draw_count ?? 0); + $paidBefore = (int) ($player->paid_draw_count ?? 0); + $freeBefore = (int) ($player->free_draw_count ?? 0); + + Db::transaction(function () use ( + $player, + $playerId, + $cost, + $coinBefore, + $coinAfter, + $addTotal, + $addPaid, + $addFree, + $totalBefore, + $paidBefore, + $freeBefore + ) { + $player->coin = $coinAfter; + $player->total_draw_count = $totalBefore + $addTotal; + $player->paid_draw_count = $paidBefore + $addPaid; + $player->free_draw_count = $freeBefore + $addFree; + $player->save(); + + DicePlayerWalletRecord::create([ + 'player_id' => $playerId, + 'coin' => -$cost, + 'type' => self::WALLET_TYPE_BUY_DRAW, + 'wallet_before' => $coinBefore, + 'wallet_after' => $coinAfter, + 'total_draw_count' => $addTotal, + 'paid_draw_count' => $addPaid, + 'free_draw_count' => $addFree, + 'remark' => "购买抽奖券{$addTotal}次(付费{$addPaid}次+赠送{$addFree}次)", + ]); + }); + + $updated = DicePlayer::find($playerId); + $userArr = $updated->hidden(['password'])->toArray(); + UserCache::setUser($playerId, $userArr); + + return [ + 'coin' => (float) $updated->coin, + 'total_draw_count' => (int) $updated->total_draw_count, + 'paid_draw_count' => (int) $updated->paid_draw_count, + 'free_draw_count' => (int) $updated->free_draw_count, + ]; + } +} diff --git a/server/config/route.php b/server/config/route.php index af61584..0d3c4c3 100644 --- a/server/config/route.php +++ b/server/config/route.php @@ -23,6 +23,8 @@ Route::group('/api', function () { Route::post('/user/logout', [app\api\controller\UserController::class, 'logout']); Route::get('/user/info', [app\api\controller\UserController::class, 'info']); Route::get('/user/balance', [app\api\controller\UserController::class, 'balance']); + Route::post('/game/buyLotteryTickets', [app\api\controller\GameController::class, 'buyLotteryTickets']); + Route::get('/game/lotteryPool', [app\api\controller\GameController::class, 'lotteryPool']); })->middleware([CheckApiAuthMiddleware::class]);