RechargeChannelConfigurationService.php 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. <?php
  2. namespace App\Services\Payment;
  3. use App\Models\RechargeChannel;
  4. use Illuminate\Support\Facades\DB;
  5. use Illuminate\Support\Facades\Schema;
  6. use RuntimeException;
  7. class RechargeChannelConfigurationService
  8. {
  9. public function options(int $dataType, ?int $id = null): array
  10. {
  11. $options = PaymentProviderCatalog::channelFormOptions($dataType);
  12. $reason = '';
  13. if ($id) {
  14. $channel = RechargeChannel::query()->findOrFail($id);
  15. if ((int)$channel->data_type !== $dataType) throw new RuntimeException('通道方向与编辑记录不一致');
  16. $reason = $this->identityLockReason($channel);
  17. }
  18. return $options + ['identity_editable' => $reason === '', 'identity_edit_reason' => $reason];
  19. }
  20. public function save(array $params): RechargeChannel
  21. {
  22. return DB::transaction(function () use ($params) {
  23. $id = (int)($params['id'] ?? 0);
  24. unset($params['id']);
  25. $channel = $id ? RechargeChannel::query()->lockForUpdate()->findOrFail($id) : new RechargeChannel();
  26. if ($channel->exists && (int)$channel->data_type !== (int)$params['data_type']) {
  27. throw new RuntimeException('不能修改通道所属的充值、提现或活动方向');
  28. }
  29. $params = PaymentProviderCatalog::normalizeChannelSelection($params);
  30. if ($channel->exists && ((int)$channel->from !== $params['from'] || (string)$channel->type !== (string)$params['type'])) {
  31. $reason = $this->identityLockReason($channel, true);
  32. if ($reason !== '') throw new RuntimeException($reason);
  33. }
  34. foreach (['name', 'key'] as $field) {
  35. if (array_key_exists($field, $params)) $params[$field] = trim((string)$params[$field]);
  36. if ((!$channel->exists || array_key_exists($field, $params)) && ($params[$field] ?? '') === '') {
  37. throw new RuntimeException($field === 'name' ? '请填写通道名称' : '请填写通道标识Key');
  38. }
  39. }
  40. foreach (['status', 'sort'] as $field) {
  41. if (array_key_exists($field, $params) && $params[$field] === null) unset($params[$field]);
  42. }
  43. if (!$channel->exists) $params += ['status' => 1, 'sort' => 0];
  44. $channel->fill($params);
  45. $channel->save();
  46. return $channel;
  47. }, 3);
  48. }
  49. private function identityLockReason(RechargeChannel $channel, bool $lock = false): string
  50. {
  51. foreach (['payment_gateways', 'payment_collection_channels', 'payment_direct_recharges'] as $table) {
  52. if (!Schema::hasTable($table) || !Schema::hasColumn($table, 'recharge_channel_id')) continue;
  53. $query = DB::table($table)->where('recharge_channel_id', $channel->id)->whereNull('deleted_at');
  54. if ($lock) $query->lockForUpdate();
  55. if ($query->first(['id'])) return '该通道已被支付配置引用,请先解除关联或新增通道,再更换公司或类型';
  56. }
  57. return '';
  58. }
  59. }