first(); } /** * Update or create * @param array $params * @return bool * @throws Exception */ public static function submit(array $params = []): bool { if (isset($params['start_time'])) $params['start_time'] = strtotime($params['start_time'] . " 00:00:00"); if (isset($params['end_time'])) $params['end_time'] = strtotime($params['end_time'] . " 23:59:59"); if (isset($params['detail_image'])) $params['detail_image'] = Util::replacePartInUrl($params['detail_image']); if (!empty($params['id'])) { $info = static::findOne(['id' => $params['id']]); if (!$info) throw new Exception("操作失败", HttpStatus::CUSTOM_ERROR); $info->update($params); } else { $info = static::$MODEL::create($params); } return true; } public static function updateBettingAmount($memberId, $amount) { $activityUser = static::findOne([ 'member_id' => $memberId, 'status' => static::$MODEL::STATUS_IN_PROGRESS ]); if ($activityUser) { $activityUser->increment('effective_betting_amount', $amount); if ($activityUser->effective_betting_amount >= $activityUser->betting_amount) { $activityUser->status = static::$MODEL::STATUS_COMPLETE; $activityUser->finish_time = time(); } $activityUser->save(); } } public static function finish($id) { $activityUser = static::findOne(['id' => $id]); $activityUser->status = static::$MODEL::STATUS_COMPLETE; $activityUser->finish_time = time(); $activityUser->save(); } /** * @throws Exception */ public static function gift($id, $amount, $bettingAmount): void { $notification = DB::transaction(function () use ($id, $amount, $bettingAmount) { $application = ActivityUser::where('id', $id)->first(); if (!$application) throw new Exception('活动不存在', HttpStatus::CUSTOM_ERROR); // Wallet first, matching deposit and settlement transactions. $wallet = WalletModel::where('member_id', $application->member_id)->lockForUpdate()->first(); if (!$wallet) throw new Exception('账户钱包不存在', HttpStatus::CUSTOM_ERROR); $activityUser = ActivityUser::where('id', $id)->lockForUpdate()->first(); if (!$activityUser) throw new Exception('活动不存在', HttpStatus::CUSTOM_ERROR); if ($activityUser->status == static::$MODEL::STATUS_IN_PROGRESS) throw new Exception('充值失败:活动进行中', HttpStatus::CUSTOM_ERROR); if ($activityUser->status == static::$MODEL::STATUS_COMPLETE) throw new Exception("充值失败:活动已完成", HttpStatus::CUSTOM_ERROR); if ($activityUser->status != static::$MODEL::STATUS_APPLY) throw new Exception('充值失败:状态异常', HttpStatus::CUSTOM_ERROR); $activity = ActivityReward::where('id', $activityUser->activity_id)->first(); if (!$activity) throw new Exception('活动不存在', HttpStatus::CUSTOM_ERROR); $eligibility = ActivityEligibilityService::evaluate($activity, ActivityEligibilityService::memberContext($activityUser->member_id)); if (!$eligibility['is_eligible']) throw new Exception($eligibility['ineligible_reason'], HttpStatus::CUSTOM_ERROR); $res = null; $granted = ActivityQuotaService::award($activity, $activityUser->member_id, $amount, function () use ($activityUser, $wallet, $amount, $bettingAmount, &$res) { $activityUser->status = static::$MODEL::STATUS_IN_PROGRESS; $activityUser->betting_amount = $bettingAmount; $activityUser->gift_amount = $amount; $activityUser->effective_betting_amount = 0; $activityUser->save(); $memberId = $activityUser->member_id; $before = (string)$wallet->available_balance; $wallet->available_balance = bcadd($before, (string)$amount, 2); $wallet->save(); $res = ['before_balance' => $before, 'after_balance' => $wallet->available_balance]; BalanceLogService::addLog($memberId, $amount, $res['before_balance'], $res['after_balance'], "优惠活动", $activityUser->id, "$activityUser->title; 赠送:$activityUser->gift_amount; 打码量:$activityUser->betting_amount"); }); if (!$granted) throw new Exception($activity->quota_enabled ? '活动获奖份数已用完,已停止新用户发奖' : '活动预算不足,已停止发奖', HttpStatus::CUSTOM_ERROR); $availableBalance = floatval($res['after_balance']); // 去除多余0后,再用 sprintf 补足两位 $availableBalance = sprintf('%.2f', $availableBalance); $text = "余额变动通知\n"; $text .= "变动金额:" . ($amount > 0 ? '+' : '') . "{$amount}\n"; $text .= "总余额为:{$availableBalance}\n"; $text .= "说明:优惠活动赠送"; return ['member_id' => $activityUser->member_id, 'text' => $text]; }); TopUpService::notifyTransferSuccess($notification['member_id'], $notification['text']); } }