| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- <?php
- namespace App\Services;
- use App\Models\RechargeChannel;
- use App\Models\RechargeChannelGroup;
- use Illuminate\Database\Eloquent\Collection as EloquentCollection;
- use Illuminate\Database\Eloquent\Model;
- use Illuminate\Support\Collection;
- use RuntimeException;
- class PaymentChannelLinkService
- {
- public function validate(int $channelId, array $groupIds, int $expectedDataType): array
- {
- $channel = RechargeChannel::query()->find($channelId);
- if (!$channel) throw new RuntimeException('充值通道不存在');
- if ((int)$channel->data_type !== $expectedDataType) {
- throw new RuntimeException($expectedDataType === 2 ? '请选择提现通道' : '请选择充值通道');
- }
- $groupIds = array_values(array_unique(array_filter(array_map('intval', $groupIds))));
- if (!$groupIds) throw new RuntimeException('至少选择一个通道组合');
- $groups = RechargeChannelGroup::query()->whereIn('id', $groupIds)->get();
- if ($groups->count() !== count($groupIds)) throw new RuntimeException('部分通道组合不存在');
- $field = $this->groupField($expectedDataType);
- foreach ($groups as $group) {
- if (!in_array((string)$channel->type, (array)$group->{$field}, true)) {
- throw new RuntimeException("通道组合“{$group->name}”没有包含通道“{$channel->name}”");
- }
- }
- return [$channel, $groupIds];
- }
- public function formatMany($models): Collection
- {
- $models = $models instanceof Collection ? $models : collect($models);
- if ($models instanceof EloquentCollection) $models->loadMissing('rechargeChannel');
- $groupIds = $models->flatMap(fn ($model) => (array)($model->recharge_channel_group_ids ?? []))
- ->map(fn ($id) => (int)$id)->filter()->unique()->values();
- $groups = RechargeChannelGroup::query()->whereIn('id', $groupIds)->get()->keyBy('id');
- return $models->map(fn (Model $model) => $this->formatOne($model, $groups));
- }
- public function formatOne(Model $model, ?Collection $groups = null): array
- {
- $model->loadMissing('rechargeChannel');
- $groups ??= RechargeChannelGroup::query()
- ->whereIn('id', (array)($model->recharge_channel_group_ids ?? []))->get()->keyBy('id');
- $channel = $model->rechargeChannel;
- $assignedIds = array_values(array_unique(array_filter(array_map(
- 'intval',
- (array)($model->recharge_channel_group_ids ?? [])
- ))));
- $effectiveIds = [];
- $unavailableIds = [];
- $groupRows = [];
- foreach ($assignedIds as $groupId) {
- $group = $groups->get($groupId);
- $effective = false;
- if ($group && $channel) {
- $effective = in_array(
- (string)$channel->type,
- (array)$group->{$this->groupField((int)$channel->data_type)},
- true
- );
- }
- if ($effective) {
- $effectiveIds[] = $groupId;
- } else {
- $unavailableIds[] = $groupId;
- }
- $groupRows[] = [
- 'id' => $groupId,
- 'name' => (string)($group->name ?? ''),
- 'effective' => $effective ? 1 : 0,
- ];
- }
- $data = $model->toArray();
- $data['recharge_channel_group_ids'] = $assignedIds;
- $data['effective_group_ids'] = $effectiveIds;
- $data['unavailable_group_ids'] = $unavailableIds;
- $data['groups'] = $groupRows;
- $data['recharge_channel'] = $channel ? [
- 'id' => (int)$channel->id,
- 'data_type' => (int)$channel->data_type,
- 'name' => (string)$channel->name,
- 'key' => (string)$channel->key,
- 'type' => (string)$channel->type,
- 'rate' => number_format((float)$channel->rate, 4, '.', ''),
- 'fee_rate' => bcmul((string)$channel->rate, '100', 4),
- 'min_amount' => $channel->min === null ? null : number_format((float)$channel->min, 2, '.', ''),
- 'max_amount' => $channel->max === null ? null : number_format((float)$channel->max, 2, '.', ''),
- 'fixed_amounts' => $channel->fixed ?: [],
- 'sort' => (int)$channel->sort,
- 'status' => (int)$channel->status,
- ] : null;
- $data['fee_rate'] = $channel ? bcmul((string)$channel->rate, '100', 4) : null;
- $data['min_amount'] = $channel?->min;
- $data['max_amount'] = $channel?->max;
- $data['sort'] = $channel ? (int)$channel->sort : null;
- $data['config_status'] = (int)$model->status;
- $data['channel_status'] = $channel ? (int)$channel->status : 0;
- $data['runtime_channel_available'] = $channel
- && (int)$channel->status === 1 && count($effectiveIds) > 0 ? 1 : 0;
- $data['effective_status'] = (int)$model->status === 1
- && $data['runtime_channel_available'] === 1 ? 1 : 0;
- if (array_key_exists('amount', $data)) {
- $data['actual_amount'] = $channel
- ? bcsub((string)$model->amount, bcmul((string)$model->amount, (string)$channel->rate, 6), 2)
- : null;
- }
- $data['channel_fields_readonly'] = [
- 'recharge_channel.name', 'recharge_channel.key', 'recharge_channel.type',
- 'fee_rate', 'min_amount', 'max_amount', 'recharge_channel.fixed_amounts',
- 'sort', 'channel_status',
- ];
- unset($data['level_scope']);
- return $data;
- }
- private function groupField(int $dataType): string
- {
- return match ($dataType) {
- 2 => 'withdraw_type',
- 3 => 'activity_type',
- default => 'recharge_type',
- };
- }
- }
|