This commit is contained in:
2026-03-05 16:50:52 +08:00
parent 39955a17a8
commit aef404548d
4 changed files with 106 additions and 59 deletions

View File

@@ -18,13 +18,13 @@ REDIS_DB = 0
# API 鉴权与用户(可选,不填则用默认值)
# authToken 签名密钥(必填,与客户端约定,用于 signature 校验)
API_AUTH_TOKEN_SECRET = xF75oK91TQj13s0UmNIr1NBWMWGfflNO
API_AUTH_TOKEN_SECRET = xF75oK91TQj13s0UmNIr1NBWMWGfflNO
# authToken 时间戳允许误差秒数,防重放,默认 300
API_AUTH_TOKEN_TIME_TOLERANCE = 300
API_AUTH_TOKEN_EXP = 86400
API_AUTH_TOKEN_TIME_TOLERANCE = 300
API_AUTH_TOKEN_EXP = 86400
# API_USER_TOKEN_EXP = 604800
API_USER_CACHE_EXPIRE = 86400
API_USER_ENCRYPT_KEY = Wj818SK8dhKBKNOY3PUTmZfhQDMCXEZi
API_USER_CACHE_EXPIRE = 86400
API_USER_ENCRYPT_KEY = Wj818SK8dhKBKNOY3PUTmZfhQDMCXEZi
# 验证码配置,支持cache|session
CAPTCHA_MODE = cache

View File

@@ -27,7 +27,8 @@ class GameLogic
/**
* 购买抽奖券
* @param int $playerId 玩家ID即 user_id
* 先更新 Redis 玩家信息(后续游玩从 Redis 读),再用事务更新数据库;事务失败则回滚 Redis
* @param int $playerId 玩家ID
* @param int $count 购买档位1 / 5 / 10
* @return array 更新后的 coin, total_ticket_count, paid_ticket_count, free_ticket_count
*/
@@ -55,59 +56,70 @@ class GameLogic
$totalBefore = (int) ($player->total_ticket_count ?? 0);
$paidBefore = (int) ($player->paid_ticket_count ?? 0);
$freeBefore = (int) ($player->free_ticket_count ?? 0);
$totalAfter = $totalBefore + $addTotal;
$paidAfter = $paidBefore + $addPaid;
$freeAfter = $freeBefore + $addFree;
Db::transaction(function () use (
$player,
$playerId,
$cost,
$coinBefore,
$coinAfter,
$addTotal,
$addPaid,
$addFree,
$totalBefore,
$paidBefore,
$freeBefore
) {
$player->coin = $coinAfter;
$player->total_ticket_count = $totalBefore + $addTotal;
$player->paid_ticket_count = $paidBefore + $addPaid;
$player->free_ticket_count = $freeBefore + $addFree;
$player->save();
$oldUserArr = $player->hidden(['password'])->toArray();
$updatedUserArr = $oldUserArr;
$updatedUserArr['coin'] = $coinAfter;
$updatedUserArr['total_ticket_count'] = $totalAfter;
$updatedUserArr['paid_ticket_count'] = $paidAfter;
$updatedUserArr['free_ticket_count'] = $freeAfter;
// 钱包流水记录
DicePlayerWalletRecord::create([
'player_id' => $playerId,
'coin' => -$cost,
'type' => self::WALLET_TYPE_BUY_DRAW,
'wallet_before' => $coinBefore,
'wallet_after' => $coinAfter,
'total_ticket_count' => $addTotal,
'paid_ticket_count' => $addPaid,
'free_ticket_count' => $addFree,
'remark' => "购买抽奖券{$addTotal}次(付费{$addPaid}次+赠送{$addFree}次)",
]);
UserCache::setUser($playerId, $updatedUserArr);
// 抽奖券获取记录
DicePlayerTicketRecord::create([
'player_id' => $playerId,
'use_coins' => $cost,
'total_ticket_count' => $addTotal,
'paid_ticket_count' => $addPaid,
'free_ticket_count' => $addFree,
'remark' => "购买抽奖券{$addTotal}次(付费{$addPaid}次+赠送{$addFree}次)",
]);
});
try {
Db::transaction(function () use (
$player,
$playerId,
$cost,
$coinBefore,
$coinAfter,
$addTotal,
$addPaid,
$addFree,
$totalAfter,
$paidAfter,
$freeAfter
) {
$player->coin = $coinAfter;
$player->total_ticket_count = $totalAfter;
$player->paid_ticket_count = $paidAfter;
$player->free_ticket_count = $freeAfter;
$player->save();
$updated = DicePlayer::find($playerId);
$userArr = $updated->hidden(['password'])->toArray();
UserCache::setUser($playerId, $userArr);
DicePlayerWalletRecord::create([
'player_id' => $playerId,
'coin' => -$cost,
'type' => self::WALLET_TYPE_BUY_DRAW,
'wallet_before' => $coinBefore,
'wallet_after' => $coinAfter,
'total_ticket_count' => $addTotal,
'paid_ticket_count' => $addPaid,
'free_ticket_count' => $addFree,
'remark' => "购买抽奖券{$addTotal}次(付费{$addPaid}次+赠送{$addFree}次)",
]);
DicePlayerTicketRecord::create([
'player_id' => $playerId,
'use_coins' => $cost,
'total_ticket_count' => $addTotal,
'paid_ticket_count' => $addPaid,
'free_ticket_count' => $addFree,
'remark' => "购买抽奖券{$addTotal}次(付费{$addPaid}次+赠送{$addFree}次)",
]);
});
} catch (\Throwable $e) {
UserCache::setUser($playerId, $oldUserArr);
throw $e;
}
return [
'coin' => (float) $updated->coin,
'total_ticket_count' => (int) $updated->total_ticket_count,
'paid_ticket_count' => (int) $updated->paid_ticket_count,
'free_ticket_count' => (int) $updated->free_ticket_count,
'coin' => (float) $coinAfter,
'total_ticket_count' => (int) $totalAfter,
'paid_ticket_count' => (int) $paidAfter,
'free_ticket_count' => (int) $freeAfter,
];
}
}

View File

@@ -49,6 +49,11 @@ class DicePlayer extends BaseModel
*/
protected $table = 'dice_player';
/** 创建时间字段dice_player 表为 created_at */
protected $createTime = 'created_at';
/** 更新时间字段dice_player 表为 updated_at */
protected $updateTime = 'updated_at';
/**
* 新增前:生成唯一 uid昵称 name 默认使用 uid
* 用 try-catch 避免表尚未含 uid 时 getAttr/getData 抛 InvalidArgumentException

View File

@@ -35,6 +35,12 @@ class BaseModel extends Model implements ModelInterface
*/
protected $updateTime = 'update_time';
/**
* 自动写入时间戳(创建时写 create_time更新时写 update_time
* @var bool
*/
protected $autoWriteTimestamp = true;
/**
* 隐藏字段
* @var array
@@ -94,24 +100,48 @@ class BaseModel extends Model implements ModelInterface
}
/**
* 新增前事件
* 新增前事件:自动写入 create_time有后台登录信息时写入 created_by
* @param Model $model
* @return void
*/
public static function onBeforeInsert($model): void
{
$info = getCurrentInfo();
$info && $model->setAttr('created_by', $info['id']);
$createTime = $model->createTime ?? 'create_time';
if ($createTime && !$model->getData($createTime)) {
$model->set($createTime, date('Y-m-d H:i:s'));
}
if (function_exists('getCurrentInfo')) {
$info = getCurrentInfo();
if (!empty($info['id'])) {
try {
$model->setAttr('created_by', $info['id']);
} catch (\Throwable $e) {
}
}
}
}
/**
* 写入前事件
* 写入前事件:更新时自动写入 update_time有后台登录信息时写入 updated_by
* @param Model $model
* @return void
*/
public static function onBeforeWrite($model): void
{
$info = getCurrentInfo();
$info && $model->setAttr('updated_by', $info['id']);
if ($model->isUpdate()) {
$updateTime = $model->updateTime ?? 'update_time';
if ($updateTime) {
$model->set($updateTime, date('Y-m-d H:i:s'));
}
}
if (function_exists('getCurrentInfo')) {
$info = getCurrentInfo();
if (!empty($info['id'])) {
try {
$model->setAttr('updated_by', $info['id']);
} catch (\Throwable $e) {
}
}
}
}
}