where('admin_id', $adminId)->find(); if (is_array($wallet)) { return $wallet; } $now = time(); Db::name('admin_wallet')->insert([ 'admin_id' => $adminId, 'balance' => '0.00', 'frozen_balance' => '0.00', 'total_income' => '0.00', 'total_withdraw' => '0.00', 'create_time' => $now, 'update_time' => $now, ]); return Db::name('admin_wallet')->where('admin_id', $adminId)->find() ?: []; } public static function creditCommission( int $adminId, ?int $channelId, string $amount, string $refType, int $refId, string $remark, ?int $operatorAdminId = null ): void { $wallet = self::ensureWallet($adminId); $before = strval($wallet['balance'] ?? '0.00'); $after = bcadd($before, $amount, 2); $now = time(); Db::name('admin_wallet')->where('admin_id', $adminId)->update([ 'balance' => $after, 'total_income' => Db::raw('total_income + ' . $amount), 'update_time' => $now, ]); Db::name('admin_wallet_record')->insert([ 'admin_id' => $adminId, 'channel_id' => $channelId, 'biz_type' => 'commission_income', 'direction' => 1, 'amount' => $amount, 'balance_before' => $before, 'balance_after' => $after, 'ref_type' => $refType, 'ref_id' => $refId, 'idempotency_key' => 'commission_income_' . $adminId . '_' . $refId, 'operator_admin_id' => $operatorAdminId, 'remark' => $remark, 'create_time' => $now, ]); } public static function applyWithdraw( int $adminId, int $channelId, string $withdrawCoin, string $receiveType, string $receiveAccount, string $idempotencyKey, string $remark ): array { $existing = Db::name('admin_withdraw_order')->where('idempotency_key', $idempotencyKey)->find(); if (is_array($existing)) { $existAdminId = intval($existing['admin_id'] ?? 0); if ($existAdminId !== $adminId) { return ['ok' => false, 'msg' => 'Idempotency key conflict']; } return [ 'ok' => true, 'order_id' => intval($existing['id'] ?? 0), 'order_no' => strval($existing['order_no'] ?? ''), 'idempotent_hit' => true, ]; } $wallet = self::ensureWallet($adminId); $before = strval($wallet['balance'] ?? '0.00'); if (bccomp($before, $withdrawCoin, 2) < 0) { return ['ok' => false, 'msg' => '钱包余额不足']; } $after = bcsub($before, $withdrawCoin, 2); $beforeFrozen = strval($wallet['frozen_balance'] ?? '0.00'); $afterFrozen = bcadd($beforeFrozen, $withdrawCoin, 2); $now = time(); $orderNo = 'AWD' . date('YmdHis') . str_pad(strval($adminId), 6, '0', STR_PAD_LEFT) . strval(random_int(1000, 9999)); Db::name('admin_wallet')->where('admin_id', $adminId)->update([ 'balance' => $after, 'frozen_balance' => $afterFrozen, 'update_time' => $now, ]); $orderId = Db::name('admin_withdraw_order')->insertGetId([ 'order_no' => $orderNo, 'admin_id' => $adminId, 'channel_id' => $channelId > 0 ? $channelId : null, 'amount' => $withdrawCoin, 'actual_amount' => $withdrawCoin, 'status' => 0, 'receive_type' => $receiveType, 'receive_account' => $receiveAccount, 'idempotency_key' => $idempotencyKey, 'review_admin_id' => null, 'review_time' => null, 'remark' => $remark, 'create_time' => $now, 'update_time' => $now, ]); Db::name('admin_wallet_record')->insert([ 'admin_id' => $adminId, 'channel_id' => $channelId > 0 ? $channelId : null, 'biz_type' => 'withdraw_freeze', 'direction' => 2, 'amount' => $withdrawCoin, 'balance_before' => $before, 'balance_after' => $after, 'ref_type' => 'admin_withdraw_order', 'ref_id' => $orderId, 'idempotency_key' => 'admin_withdraw_freeze_' . $orderId, 'operator_admin_id' => $adminId, 'remark' => $remark !== '' ? $remark : '管理员提现申请冻结', 'create_time' => $now, ]); return ['ok' => true, 'order_id' => $orderId, 'order_no' => $orderNo]; } public static function approveWithdraw(array $order, int $reviewAdminId, string $remark): void { $orderId = intval($order['id'] ?? 0); $adminId = intval($order['admin_id'] ?? 0); $amount = strval($order['amount'] ?? '0.00'); $wallet = self::ensureWallet($adminId); $frozen = strval($wallet['frozen_balance'] ?? '0.00'); $afterFrozen = bcsub($frozen, $amount, 2); $now = time(); Db::name('admin_wallet')->where('admin_id', $adminId)->update([ 'frozen_balance' => $afterFrozen, 'total_withdraw' => Db::raw('total_withdraw + ' . $amount), 'update_time' => $now, ]); Db::name('admin_withdraw_order')->where('id', $orderId)->update([ 'status' => 1, 'review_admin_id' => $reviewAdminId, 'review_time' => $now, 'remark' => $remark, 'update_time' => $now, ]); Db::name('admin_wallet_record')->insert([ 'admin_id' => $adminId, 'channel_id' => $order['channel_id'] ?? null, 'biz_type' => 'withdraw_success', 'direction' => 2, 'amount' => $amount, 'balance_before' => strval($wallet['balance'] ?? '0.00'), 'balance_after' => strval($wallet['balance'] ?? '0.00'), 'ref_type' => 'admin_withdraw_order', 'ref_id' => $orderId, 'idempotency_key' => 'admin_withdraw_success_' . $orderId, 'operator_admin_id' => $reviewAdminId, 'remark' => $remark !== '' ? $remark : '管理员提现审核通过', 'create_time' => $now, ]); } public static function rejectWithdraw(array $order, int $reviewAdminId, string $remark): void { $orderId = intval($order['id'] ?? 0); $adminId = intval($order['admin_id'] ?? 0); $amount = strval($order['amount'] ?? '0.00'); $wallet = self::ensureWallet($adminId); $before = strval($wallet['balance'] ?? '0.00'); $after = bcadd($before, $amount, 2); $frozen = strval($wallet['frozen_balance'] ?? '0.00'); $afterFrozen = bcsub($frozen, $amount, 2); $now = time(); Db::name('admin_wallet')->where('admin_id', $adminId)->update([ 'balance' => $after, 'frozen_balance' => $afterFrozen, 'update_time' => $now, ]); Db::name('admin_withdraw_order')->where('id', $orderId)->update([ 'status' => 2, 'review_admin_id' => $reviewAdminId, 'review_time' => $now, 'remark' => $remark, 'update_time' => $now, ]); Db::name('admin_wallet_record')->insert([ 'admin_id' => $adminId, 'channel_id' => $order['channel_id'] ?? null, 'biz_type' => 'withdraw_refund', 'direction' => 1, 'amount' => $amount, 'balance_before' => $before, 'balance_after' => $after, 'ref_type' => 'admin_withdraw_order', 'ref_id' => $orderId, 'idempotency_key' => 'admin_withdraw_refund_' . $orderId, 'operator_admin_id' => $reviewAdminId, 'remark' => $remark !== '' ? $remark : '管理员提现审核拒绝退回', 'create_time' => $now, ]); } }