Parcourir la source

只保留公链

doge il y a 1 heure
Parent
commit
1806b06fe7

+ 1 - 21
app/Http/Controllers/admin/Config.php

@@ -459,9 +459,7 @@ class Config extends Controller
      * @apiParam {string} brokerage 抽佣比例
      * @apiParam {string} service_charge 提现手续费
      * @apiParam {string} service_account 客服账号
-     * @apiParam {string} receiving_address TRC20充值收款地址
-     * @apiParam {string} [receiving_address_erc20] ERC20充值收款地址
-     * @apiParam {string} [public_chain] Public Chain 公链地址,最多2048字符
+     * @apiParam {string} receiving_address 充值收款地址
      * @apiParam {string} receiving_type 收款方式 1-自动 2-手动
      *
      */
@@ -476,8 +474,6 @@ class Config extends Controller
                 'service_charge' => ['required', 'integer', 'min:1'],
                 'service_account' => ['required', 'string', 'min:1'],
                 'receiving_address' => ['required', 'string', 'min:34'],
-                'receiving_address_erc20' => ['sometimes', 'nullable', 'string', 'regex:/^0x[0-9a-fA-F]{40}$/'],
-                'public_chain' => ['sometimes', 'nullable', 'string', 'max:2048'],
                 'receiving_type' => ['required', 'integer', 'in:1,2']
             ]);
             $baseScore = request()->input('base_score');
@@ -501,22 +497,6 @@ class Config extends Controller
             ConfigModel::where('field', 'receiving_address')
                 ->update(['val' => $val]);
 
-            if (request()->exists('receiving_address_erc20')) {
-                ConfigModel::updateOrCreate(['field' => 'receiving_address_erc20'], [
-                    'val' => request()->input('receiving_address_erc20') ?? '',
-                    'remark' => '收款地址_ERC20',
-                    'group_id' => 1,
-                ]);
-            }
-
-            if (request()->exists('public_chain')) {
-                ConfigModel::updateOrCreate(['field' => 'public_chain'], [
-                    'val' => trim(request()->input('public_chain') ?? ''),
-                    'remark' => 'Public Chain 公链地址',
-                    'group_id' => 1,
-                ]);
-            }
-
             $val = request()->input('receiving_type');
             ConfigModel::where('field', 'receiving_type')
                 ->update(['val' => $val]);

+ 7 - 17
app/Http/Controllers/api/Wallet.php

@@ -124,9 +124,6 @@ class Wallet extends BaseController
 
     /**
      * 获取充值二维码(USDT充值)
-     * type 支持 TRC20/ERC20;address 为对应公链的收款地址。
-     * public_chain 为后台独立填写的 Public Chain 地址。
-     * 手动模式读取后台配置,自动模式使用会员专属的 TRC20 地址。
      */
     public function scan()
     {
@@ -136,28 +133,24 @@ class Wallet extends BaseController
                 'type' => ['required', 'string'],
             ]);
 
-            $net = strtolower($params['type']);
-            if (!in_array($net, ['trc20', 'erc20'], true)) {
+            if (strtolower($params['type']) === "trc20") {
+                $address = Config::where('field', 'receiving_address')->first()->val;
+            } elseif (strtolower($params['type']) === "erc20") {
+                $address = Config::where('field', 'receiving_address_erc20')->first()->val;
+            } else {
                 return $this->error(lang('充值类型错误'));
             }
 
             $receivingType = ConfigService::getVal("receiving_type");
             //自动充值
             if ($receivingType == 1) {
-                if ($net !== 'trc20') {
-                    return $this->error(lang('自动充值仅支持TRC20'));
-                }
                 $res = WalletService::getRechargeImageAddress($member_id);
                 $address = $res['address'];
                 $qrCode = $res['full_path'];
             } else {
                 //手动充值
-                $field = $net === 'trc20' ? 'receiving_address' : 'receiving_address_erc20';
-                $address = trim((string)Config::where('field', $field)->value('val'));
-                if ($address === '') {
-                    return $this->error(lang('该公链收款地址未配置,请联系客服'));
-                }
                 $res = WalletService::getPlatformImageAddress($address);
+                $res['net'] = $params['type'];
                 $qrCode = $res['full_path'];
             }
             
@@ -165,10 +158,7 @@ class Wallet extends BaseController
                 'qrcode' => $qrCode,
                 'address' => $address,
                 'public_chain' => (string)(Config::where('field', 'public_chain')->value('val') ?? ''),
-                'net' => strtoupper($net),
-                'coin' => 'USDT',
-                'receiving_type' => (int)$receivingType,
-            ])->header('Cache-Control', 'no-store');
+            ]);
         } catch (ValidationException $e) {
             return $this->error($e->validator->errors()->first());
         } catch (\Exception $e) {

+ 9 - 32
app/Services/UsdtRechargeConfigService.php

@@ -3,53 +3,30 @@
 namespace App\Services;
 
 use App\Models\Config;
-use Illuminate\Support\Facades\DB;
-use Illuminate\Validation\ValidationException;
 
 class UsdtRechargeConfigService
 {
     public function get(): array
     {
-        $values = Config::whereIn('field', ['receiving_type', 'receiving_address', 'receiving_address_erc20', 'public_chain'])
-            ->pluck('val', 'field');
-
         return [
-            'receiving_type' => (int)($values['receiving_type'] ?? 2),
-            'receiving_address' => (string)($values['receiving_address'] ?? ''),
-            'receiving_address_erc20' => (string)($values['receiving_address_erc20'] ?? ''),
-            'public_chain' => (string)($values['public_chain'] ?? ''),
+            'public_chain' => (string)(Config::where('field', 'public_chain')->value('val') ?? ''),
         ];
     }
 
     public function save(array $input): array
     {
-        foreach (['receiving_address', 'receiving_address_erc20', 'public_chain'] as $field) {
-            if (isset($input[$field]) && is_string($input[$field])) {
-                $input[$field] = trim($input[$field]);
-            }
+        if (isset($input['public_chain']) && is_string($input['public_chain'])) {
+            $input['public_chain'] = trim($input['public_chain']);
         }
         $data = validator($input, [
-            'receiving_type' => ['required', 'integer', 'in:1,2'],
-            'receiving_address' => ['present', 'nullable', 'string', 'regex:/^T[1-9A-HJ-NP-Za-km-z]{33}$/'],
-            'receiving_address_erc20' => ['present', 'nullable', 'string', 'regex:/^0x[0-9a-fA-F]{40}$/'],
-            'public_chain' => ['sometimes', 'nullable', 'string', 'max:2048'],
+            'public_chain' => ['present', 'nullable', 'string', 'max:2048'],
         ])->validate();
 
-        if ((int)$data['receiving_type'] === 2 && empty($data['receiving_address']) && empty($data['receiving_address_erc20'])) {
-            throw ValidationException::withMessages(['receiving_address' => '手动充值至少填写一个公链收款地址']);
-        }
-
-        DB::transaction(function () use ($data) {
-            $fields = ['receiving_type' => '充值方式:1自动 2手动', 'receiving_address' => '收款地址_TRC20', 'receiving_address_erc20' => '收款地址_ERC20'];
-            if (array_key_exists('public_chain', $data)) {
-                $fields['public_chain'] = 'Public Chain 公链地址';
-            }
-            foreach ($fields as $field => $remark) {
-                Config::updateOrCreate(['field' => $field], [
-                    'val' => (string)($data[$field] ?? ''), 'remark' => $remark, 'group_id' => 1,
-                ]);
-            }
-        });
+        Config::updateOrCreate(['field' => 'public_chain'], [
+            'val' => $data['public_chain'] ?? '',
+            'remark' => 'Public Chain 公链地址',
+            'group_id' => 1,
+        ]);
 
         return $this->get();
     }

+ 6 - 20
docs/前端接口/USDT公链收款地址-前台接入.md

@@ -1,29 +1,15 @@
-# USDT公链收款地址:前台接入
+# Public Chain 公链地址:前台接入
 
-`GET /api/wallet/scan?type=trc20`,使用原会员登录凭证。`type` 支持 `trc20`、`erc20`,不区分大小写。
+原接口 `GET /api/wallet/scan?type=trc20` 只新增 `data.public_chain`,内容来自后台唯一的「Public Chain 公链地址」输入框。
 
-成功 `code=0`,`data` 结构如下;示例中的地址及图片路径需使用实际接口返回值:
+成功响应的 `data` 示例:
 
 ```json
 {
   "qrcode": "https://example.com/storage/recharge/<address>.png",
-  "address": "<address>",
-  "public_chain": "<后台填写的Public Chain地址>",
-  "net": "TRC20",
-  "coin": "USDT",
-  "receiving_type": 2
+  "address": "<原收款地址>",
+  "public_chain": "<后台填写的公链地址>"
 }
 ```
 
-- `address`:对应公链的实际收款地址,直接展示并用于复制。保留原字段名。
-- `public_chain`:新增,独立的 Public Chain 公链地址,由后台手动填写,按纯文本展示或复制。两条链及自动/手动模式共用此配置,未配置返回 `""`,此时隐藏对应展示。
-- `qrcode`:同一收款地址的二维码。
-- `net`:新增,当前公链 `TRC20` 或 `ERC20`。
-- `coin`:新增,固定为 `USDT`。
-- `receiving_type`:新增,`1` 自动、`2` 手动。
-
-手动模式的地址由后台填写,两条公链分别配置。未配置所选公链时 `code=-1`,展示 `msg`,不要复用之前的地址和二维码。
-
-自动模式使用会员专属 TRC20 地址,ERC20 请求返回 `code=-1`,不会返回其他链的地址。切换公链时重新请求本接口,并同时更新地址、二维码和链名称;响应禁止缓存。
-
-手动充值凭证仍提交 `/api/wallet/recharge`,`net` 使用返回的 `net`,`toAddress` 使用返回的 `address`,其余参数沿用原接口。
+`public_chain` 未配置时返回 `""`,隐藏对应展示;有值时按纯文本展示或复制。`qrcode`、`address` 及原有充值流程照常使用。本次不新增 `net`、`coin` 或 `receiving_type` 返回字段。

+ 13 - 25
docs/总后台/USDT公链收款地址-后台接入.md

@@ -1,38 +1,26 @@
-# USDT公链收款地址:后台接入
+# Public Chain 公链地址:后台接入
 
-在后台 USDT 充值设置中增加充值模式、TRC20 收款地址、ERC20 收款地址、Public Chain 公链地址四个输入项。`public_chain` 是独立配置字段,与已有的 USDT 收款地址分别填写。此项目提供后台接口,管理页面需按本文接入。
+页面只增加一个「Public Chain 公链地址」输入框,对应 `public_chain`。移除本次误加的 TRC20、ERC20 收款地址输入框及手动/自动选项。
 
 | 方法 | 接口 | 用途 | 沿用权限 URI |
 | --- | --- | --- | --- |
-| GET | `/admin/config/usdt` | 读取当前配置 | `admin/config/getAll` |
-| POST | `/admin/config/usdt` | 保存充值配置及 Public Chain | `admin/config/set` |
+| GET | `/admin/config/usdt` | 读取公链地址 | `admin/config/getAll` |
+| POST | `/admin/config/usdt` | 保存公链地址 | `admin/config/set` |
 
-使用后台登录凭证 `Authorization: Bearer <admin_token>`,POST 使用 JSON。无需额外数据库迁移,沿用 `config` 表的现有字段,缺失记录在保存时创建。
-
-读取成功的 `data`、保存请求和保存成功的 `data` 使用相同结构:
+使用后台登录凭证 `Authorization: Bearer <admin_token>`,POST 使用 JSON。保存只需提交一个字段:
 
 ```json
-{
-  "receiving_type": 2,
-  "receiving_address": "",
-  "receiving_address_erc20": "",
-  "public_chain": ""
-}
+{"public_chain":"后台填写的公链地址"}
 ```
 
-上例表示未配置时的读取结果;保存手动模式前需至少填写一个地址。
-
-| 字段 | 页面名称 | 规则 |
-| --- | --- | --- |
-| `receiving_type` | 充值模式 | `1` 自动,`2` 手动 |
-| `receiving_address` | TRC20 公链收款地址 | T 开头、34位 Base58 字符,可留空 |
-| `receiving_address_erc20` | ERC20 公链收款地址 | 0x 开头、后接40位十六进制字符,可留空 |
-| `public_chain` | Public Chain 公链地址 | 可手动填写的独立字符串,最多2048字符,可留空 |
+读取成功及保存成功的 `data` 均只包含:
 
-每次保存必须提交充值模式及两个收款地址字段。地址首尾空白会移除,空字符串或 `null` 清空该链地址;手动模式至少填写一条链的地址。只校验收款地址格式,不验证链上账户或所有权。
+```json
+{"public_chain":"后台填写的公链地址"}
+```
 
-`public_chain` 首尾空白会移除,传空字符串或 `null` 清空,省略则保留原值。未配置时读取和扫码接口均返回 `""`。它是一项共用配置,`/api/wallet/scan` 在两条公链、自动及手动模式下都通过 `data.public_chain` 返回保存的内容,不从 `address` 或 `net` 推导。前台按纯文本展示或复制。
+`public_chain` 为字符串,最多2048字符;保存时移除首尾空白,空字符串或 `null` 清空,必须提交此字段。未配置时读取返回 `""`。
 
-`code=0` 保存成功,使用返回 `data` 回填表单;`code=-3` 显示 `msg`。保存后 `/api/wallet/scan?type=trc20` 或 `type=erc20` 按所选公链返回配置的收款地址及对应二维码;未填写该链地址时返回错误。自动模式继续使用会员专属 TRC20 地址,ERC20 请求返回错误。
+保存成功 `code=0`,用返回 `data.public_chain` 回填唯一输入框;校验失败 `code=-3`,展示 `msg`。
 
-旧接口 `/admin/config/getAll`、`/admin/config/get`、`/admin/config/setField` 继续使用同一组配置;`/admin/config/set` 也支持可选的 `receiving_address_erc20`、`public_chain`,省略时保留原值。新页面使用独立接口,无需携带房间底分、抽佣等其他设置。
+配置保存在现有 `config` 表的 `public_chain`,无需数据库迁移。本接口仅修改该字段,原有充值模式和收款地址沿用原逻辑。`/api/wallet/scan` 在原返回中增加 `data.public_chain`。

+ 41 - 94
tests/Integration/UsdtRechargeConfigTest.php

@@ -83,11 +83,6 @@ class UsdtRechargeConfigTest extends TestCase
         parent::tearDown();
     }
 
-    private function settings(array $changes = []): array
-    {
-        return array_replace(['receiving_type' => 2, 'receiving_address' => self::TRC, 'receiving_address_erc20' => self::ERC, 'public_chain' => ''], $changes);
-    }
-
     private function request(string $path, string $method, array $params): void
     {
         $request = Request::create($path, $method, $params);
@@ -95,113 +90,65 @@ class UsdtRechargeConfigTest extends TestCase
         $this->app->instance('request', $request);
     }
 
-    private function scan(string $type): array
+    private function save(array $params): array
     {
-        $this->request('/api/wallet/scan', 'GET', ['type' => $type]);
-        return (new Wallet())->scan()->getData(true);
+        $this->request('/admin/config/usdt', 'POST', $params);
+        return (new AdminConfig())->saveUsdt($this->service)->getData(true);
     }
 
-    public function test_admin_saves_and_reads_both_addresses_without_other_system_settings(): void
+    private function seedOriginalSettings(): array
     {
-        $this->assertSame($this->settings(['receiving_address' => '', 'receiving_address_erc20' => '']), $this->service->get());
-        $this->request('/admin/config/usdt', 'POST', $this->settings(['receiving_address' => ' ' . self::TRC . ' ']));
-        $response = (new AdminConfig())->saveUsdt($this->service);
-        $this->assertSame(0, $response->getData(true)['code']);
-        $this->assertSame($this->settings(), $response->getData(true)['data']);
-        $this->assertStringContainsString('no-store', $response->headers->get('Cache-Control'));
-        $this->assertSame($this->settings(), (new AdminConfig())->usdt($this->service)->getData(true)['data']);
-        $this->service->save($this->settings());
-        $this->assertSame(4, DB::table('config')->count());
+        $settings = ['receiving_type' => '2', 'receiving_address' => self::TRC, 'receiving_address_erc20' => self::ERC];
+        foreach ($settings as $field => $val) DB::table('config')->insert(compact('field', 'val'));
+        return $settings;
     }
 
-    public function test_scan_returns_selected_manually_configured_address_and_matching_qr(): void
+    public function test_admin_reads_and_saves_only_one_public_chain_field(): void
     {
-        $this->service->save($this->settings());
-        foreach (['TrC20' => self::TRC, 'erc20' => self::ERC] as $type => $address) {
-            $result = $this->scan($type);
-            $this->assertSame(0, $result['code']);
-            $this->assertSame([
-                'qrcode' => 'https://example.test/storage/recharge/' . $address . '.png',
-                'address' => $address, 'public_chain' => '', 'net' => strtoupper($type), 'coin' => 'USDT', 'receiving_type' => 2,
-            ], $result['data']);
-        }
-    }
-
-    public function test_public_chain_saves_independently_returns_in_scan_and_can_be_cleared(): void
-    {
-        $this->request('/admin/config/usdt', 'POST', $this->settings(['public_chain' => ' public-chain-address ']));
-        $saved = (new AdminConfig())->saveUsdt($this->service)->getData(true);
+        $this->assertSame(['public_chain' => ''], $this->service->get());
+        $saved = $this->save(['public_chain' => ' public-chain-address ']);
         $this->assertSame(0, $saved['code']);
-        $this->assertSame('public-chain-address', $saved['data']['public_chain']);
-        foreach (['trc20', 'erc20'] as $type) {
-            $this->assertSame('public-chain-address', $this->scan($type)['data']['public_chain']);
-        }
-        $withoutPublicChain = $this->settings();
-        unset($withoutPublicChain['public_chain']);
-        $this->service->save($withoutPublicChain);
-        $this->assertSame('public-chain-address', $this->service->get()['public_chain']);
-        $this->service->save($this->settings(['public_chain' => null]));
-        $this->assertSame('', $this->scan('trc20')['data']['public_chain']);
-        $this->assertSame(self::TRC, $this->scan('trc20')['data']['address']);
+        $this->assertSame(['public_chain' => 'public-chain-address'], $saved['data']);
+        $this->assertSame($saved['data'], (new AdminConfig())->usdt($this->service)->getData(true)['data']);
+        $this->assertSame(['public_chain'], DB::table('config')->pluck('field')->all());
+        $this->assertSame(0, $this->save(['public_chain' => null])['code']);
+        $this->assertSame(['public_chain' => ''], $this->service->get());
     }
 
-    public function test_blank_or_missing_chain_address_does_not_generate_a_qr_or_use_other_chain(): void
+    public function test_saving_public_chain_does_not_modify_original_addresses_or_mode(): void
     {
-        $this->service->save($this->settings(['receiving_address_erc20' => '']));
-        $this->assertSame(-1, $this->scan('erc20')['code']);
-        DB::table('config')->where('field', 'receiving_address')->delete();
-        $this->assertSame(-1, $this->scan('trc20')['code']);
-        $this->assertCount(2, glob($this->storage . '/app/public/recharge/*'));
-    }
-
-    public function test_automatic_mode_rejects_erc20_instead_of_returning_a_tron_address(): void
-    {
-        $this->service->save($this->settings(['receiving_type' => 1]));
-        $this->assertSame(-1, $this->scan('erc20')['code']);
-        $this->assertSame(-1, $this->scan('bep20')['code']);
-    }
-
-    public function test_automatic_trc20_uses_member_wallet_even_without_platform_addresses(): void
-    {
-        $this->service->save($this->settings(['receiving_type' => 1, 'receiving_address' => '', 'receiving_address_erc20' => '']));
-        DB::table('config')->where('field', '!=', 'receiving_type')->delete();
-        DB::statement('CREATE TABLE bot_wallets (id INTEGER PRIMARY KEY,member_id TEXT,coin TEXT,net TEXT,address TEXT,available_balance TEXT,frozen_balance TEXT)');
-        DB::table('wallets')->insert(['id' => 1, 'member_id' => 'member-1', 'coin' => 'USDT', 'net' => 'TRC20',
-            'address' => self::TRC, 'available_balance' => '0', 'frozen_balance' => '0']);
-        $this->app->instance('cache', new \Illuminate\Cache\Repository(new \Illuminate\Cache\ArrayStore()));
-        $result = $this->scan('trc20');
-        $this->assertSame(0, $result['code']);
-        $this->assertSame(self::TRC, $result['data']['address']);
-        $this->assertSame(1, $result['data']['receiving_type']);
-        $this->assertArrayHasKey('member-1', $this->app['cache']->get('usdt_recharge_pending_sync_members'));
+        $settings = $this->seedOriginalSettings();
+        $saved = $this->save(['public_chain' => 'public-chain-address',
+            'receiving_type' => 1, 'receiving_address' => 'ignored', 'receiving_address_erc20' => 'ignored']);
+        $this->assertSame(0, $saved['code']);
+        $this->assertSame(['public_chain' => 'public-chain-address'], $saved['data']);
+        $this->assertSame($settings, DB::table('config')->where('field', '!=', 'public_chain')->pluck('val', 'field')->all());
     }
 
-    public function test_invalid_settings_do_not_partially_overwrite_saved_addresses(): void
+    public function test_scan_only_adds_public_chain_to_the_original_response(): void
     {
-        $this->service->save($this->settings());
-        foreach ([['receiving_type' => 3], ['receiving_address' => self::ERC],
-            ['receiving_address_erc20' => self::TRC], ['receiving_address' => '../invalid'],
-            ['receiving_address' => '', 'receiving_address_erc20' => ''],
-            ['public_chain' => ['invalid']], ['public_chain' => str_repeat('a', 2049)]] as $change) {
-            $this->request('/admin/config/usdt', 'POST', $this->settings($change));
-            $this->assertSame(-3, (new AdminConfig())->saveUsdt($this->service)->getData(true)['code']);
-            $this->assertSame($this->settings(), $this->service->get());
+        $this->seedOriginalSettings();
+        $this->save(['public_chain' => 'public-chain-address']);
+        foreach (['TrC20' => self::TRC, 'erc20' => self::ERC] as $type => $address) {
+            $this->request('/api/wallet/scan', 'GET', ['type' => $type]);
+            $result = (new Wallet())->scan()->getData(true);
+            $this->assertSame(0, $result['code']);
+            $this->assertSame([
+                'qrcode' => 'https://example.test/storage/recharge/' . $address . '.png',
+                'address' => $address, 'public_chain' => 'public-chain-address',
+            ], $result['data']);
         }
+        DB::table('config')->where('field', 'public_chain')->delete();
+        $this->assertSame('', (new Wallet())->scan()->getData(true)['data']['public_chain']);
     }
 
-    public function test_existing_config_save_can_include_erc20_and_omission_preserves_it(): void
+    public function test_invalid_or_omitted_public_chain_does_not_overwrite_saved_value(): void
     {
-        $this->service->save($this->settings());
-        $params = $this->settings(['receiving_address_erc20' => '0x' . str_repeat('a', 40), 'public_chain' => 'public-chain-address']) + [
-            'base_score' => [1], 'brokerage' => '0.1', 'service_charge' => 1, 'service_account' => 'support',
-        ];
-        $this->request('/admin/config/set', 'POST', $params);
-        $this->assertSame(0, (new AdminConfig())->set()->getData(true)['code']);
-        unset($params['receiving_address_erc20'], $params['public_chain']);
-        $this->request('/admin/config/set', 'POST', $params);
-        $this->assertSame(0, (new AdminConfig())->set()->getData(true)['code']);
-        $this->assertSame('0x' . str_repeat('a', 40), $this->service->get()['receiving_address_erc20']);
-        $this->assertSame('public-chain-address', $this->service->get()['public_chain']);
+        $this->save(['public_chain' => 'saved-address']);
+        foreach ([[], ['public_chain' => []], ['public_chain' => str_repeat('a', 2049)]] as $params) {
+            $this->assertSame(-3, $this->save($params)['code']);
+            $this->assertSame(['public_chain' => 'saved-address'], $this->service->get());
+        }
     }
 
     public function test_routes_keep_admin_auth_and_existing_configuration_permissions(): void