PaymentProviderService.php 4.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. <?php
  2. namespace App\Services\Payment;
  3. use App\Models\PaymentProvider;
  4. use App\Models\RechargeChannel;
  5. use App\Services\OperationAuditService;
  6. use Illuminate\Support\Facades\DB;
  7. use InvalidArgumentException;
  8. use RuntimeException;
  9. class PaymentProviderService
  10. {
  11. public static function statuses(): array
  12. {
  13. // No process-wide cache: long-running workers must see the latest switch.
  14. return PaymentProvider::query()->pluck('status', 'code')->map(fn ($status) => (int)$status)->all();
  15. }
  16. public static function assertEnabled(string $code): void
  17. {
  18. if (!in_array($code, PaymentProviderCatalog::codes(), true)) throw new InvalidArgumentException('支付公司不存在');
  19. if ((self::statuses()[$code] ?? 0) !== 1) throw new RuntimeException(PaymentProviderCatalog::label($code) . '已禁用');
  20. }
  21. public static function requestEnabled(string $channel, int $direction): bool
  22. {
  23. // Mirror actual dispatch, including historical aliases accepted by provider services.
  24. if (JdPayService::isChannel($channel)) $code = 'jd';
  25. elseif ($direction === 1 ? NoPayService::isRechargeChannel($channel) : NoPayService::isWithdrawChannel($channel)) $code = 'no';
  26. elseif ($direction === 1 ? ZimuPayService::isRechargeChannel($channel) : ZimuPayService::isPayoutChannel($channel)) $code = 'zimu';
  27. else $code = $direction === 1 ? 'sanjin' : 'qianbao';
  28. return (self::statuses()[$code] ?? 0) === 1;
  29. }
  30. public function listing(array $params): array
  31. {
  32. $channels = RechargeChannel::query()->get(['from', 'data_type', 'type', 'status'])->toArray();
  33. $definitions = PaymentProviderCatalog::definitions();
  34. $rows = PaymentProvider::query()->whereIn('code', array_keys($definitions))->orderBy('id')->get()
  35. ->map(function ($provider) use ($definitions, $channels) {
  36. $code = $provider->code;
  37. $definition = $definitions[$code];
  38. $matching = array_filter($channels, fn ($channel) => (PaymentProviderCatalog::channelIdentity($channel)['provider_code'] ?? null) === $code);
  39. return [
  40. 'id' => (int)$provider->id, 'payment_company' => $code, 'payment_company_label' => $definition['label'],
  41. 'data_types' => $definition['directions'], 'signature_algorithm' => $definition['signature'],
  42. 'status' => (int)$provider->status, 'status_text' => $provider->status === 1 ? '启用' : '禁用',
  43. 'channel_count' => count($matching),
  44. 'enabled_channel_count' => count(array_filter($matching, fn ($channel) => (int)$channel['status'] === 1)),
  45. 'created_at' => $provider->created_at, 'updated_at' => $provider->updated_at,
  46. ];
  47. })->filter(function ($row) use ($params) {
  48. if (!empty($params['payment_company']) && $row['payment_company'] !== $params['payment_company']) return false;
  49. if (isset($params['status']) && $row['status'] !== (int)$params['status']) return false;
  50. return empty($params['data_type']) || in_array((int)$params['data_type'], $row['data_types'], true);
  51. })->values();
  52. $page = (int)($params['page'] ?? 1);
  53. $limit = (int)($params['limit'] ?? 20);
  54. return ['total' => $rows->count(), 'data' => $rows->forPage($page, $limit)->values()->all()];
  55. }
  56. public function setStatus(string $code, int $status): void
  57. {
  58. if (!in_array($code, PaymentProviderCatalog::codes(), true) || !in_array($status, [0, 1], true)) {
  59. throw new InvalidArgumentException('支付公司或状态错误');
  60. }
  61. DB::transaction(function () use ($code, $status) {
  62. $provider = PaymentProvider::query()->where('code', $code)->lockForUpdate()->firstOrFail();
  63. if ($provider->status === $status) return;
  64. $before = $provider->toArray();
  65. $provider->status = $status;
  66. $provider->save();
  67. OperationAuditService::record('payment_company', (int)$provider->id, 'update', $before, $provider);
  68. }, 3);
  69. }
  70. }