virtualPayService = new VirtualPayService(); } catch (\Exception $e) { } } /** * 查询商家账户可提现余额 * @return mixed */ public function queryBizBalance() { if (!$this->virtualPayService) { return $this->error('虚拟支付未配置,请先完成虚拟支付配置'); } try { $result = $this->virtualPayService->queryBizBalance(); } catch (\Exception $e) { return $this->error('查询余额失败:' . $e->getMessage()); } if (isset($result['errcode']) && $result['errcode'] !== 0) { return $this->error('查询失败:' . ($result['errmsg'] ?? '未知错误')); } return $this->success('查询成功', $result); } /** * 创建提现单 * @return mixed */ public function createWithdraw() { if (!$this->virtualPayService) { return $this->error('虚拟支付未配置,请先完成虚拟支付配置'); } $virtualPayConfig = \app\common\model\config\System::getConfig('virtual_pay'); if (isset($virtualPayConfig['balance_withdraw_switch']) && $virtualPayConfig['balance_withdraw_switch'] === 'close') { return $this->error('余额提现功能已关闭'); } $amount = $this->request->post('amount', ''); $withdrawId = $this->request->post('withdraw_no', ''); if (empty($withdrawId)) { $withdrawId = $this->virtualPayService->generateWithdrawNo(); } if (strlen($withdrawId) < 8 || strlen($withdrawId) > 32) { return $this->error('提现单号长度必须在8-32个字符之间'); } if ($amount !== '' && (!is_numeric($amount) || $amount <= 0)) { return $this->error('提现金额必须大于0'); } try { $result = $this->virtualPayService->createWithdrawOrder($withdrawId, $amount); } catch (\Exception $e) { return $this->error('创建提现单失败:' . $e->getMessage()); } if (isset($result['errcode']) && $result['errcode'] !== 0) { return $this->error('提现失败:' . ($result['errmsg'] ?? '未知错误')); } $data = [ 'withdraw_no' => $result['withdraw_no'] ?? $withdrawId, 'wx_withdraw_no' => $result['wx_withdraw_no'] ?? '', ]; return $this->success('提现单创建成功', $data); } /** * 查询提现单 * @return mixed */ public function queryWithdraw() { if (!$this->virtualPayService) { return $this->error('虚拟支付未配置,请先完成虚拟支付配置'); } $withdrawId = $this->request->post('withdraw_no', ''); if (empty($withdrawId)) { return $this->error('提现单号不能为空'); } try { $result = $this->virtualPayService->queryWithdrawOrder($withdrawId); } catch (\Exception $e) { return $this->error('查询提现单失败:' . $e->getMessage()); } if (isset($result['errcode']) && $result['errcode'] !== 0) { return $this->error('查询失败:' . ($result['errmsg'] ?? '未知错误')); } $statusMap = [1 => '提现中', 2 => '提现成功', 3 => '提现失败']; if (isset($result['status'])) { $result['status_text'] = $statusMap[$result['status']] ?? '未知'; } return $this->success('查询成功', $result); } /** * 获取虚拟支付配置 * @return mixed */ public function getConfig() { $config = \app\common\model\config\System::getConfig('virtual_pay'); if (!$config) { return $this->error('配置不存在'); } $config['exchange_rate'] = $config['exchange_rate'] ?? '1'; return $this->success('获取成功', $config); } /** * 保存虚拟支付配置 * @return mixed */ public function setConfig() { $row = $this->request->post("row/a", [], 'trim'); if (!$row) { return $this->error('参数不能为空'); } $configName = 'virtual_pay'; $config = \app\common\model\config\System::load($configName); if (!$config) { return $this->error('配置不存在'); } $config = $this->syncConfigWithDefault($configName, $config); foreach ($config as &$item) { if (isset($row[$item['name']])) { $value = $row[$item['name']]; if ($item['name'] === 'virtual_goods_types') { $value = $this->normalizeVirtualGoodsTypes($value); } if ($item['name'] === 'exchange_rate') { $value = in_array(intval($value), [1, 10, 100], true) ? (string)intval($value) : '1'; } $item['value'] = $value; } } $model = new \app\admin\model\config\System(); $dbRow = $model->where(['name' => $configName])->find(); if ($dbRow) { $dbRow->value = json_encode(array_values($config), JSON_UNESCAPED_UNICODE); $dbRow->save(); } Cache::rm(\app\common\constant\cache\Keys::SYSTEM_CONFIG($configName)); \think\Log::info('[VirtualPay] 配置已更新,缓存已清除'); return $this->success('保存成功'); } /** * 补齐新增的默认配置项,保留已有值。 * @param string $configName * @param array $config * @return array */ private function syncConfigWithDefault($configName, $config) { $defaultConfig = \app\common\model\fill\Handle::getSystemDefaultConfig($configName); if (!$defaultConfig) { return $config; } $configMap = []; foreach ($config as $item) { if (isset($item['name'])) { $configMap[$item['name']] = $item; } } $result = []; foreach ($defaultConfig as $defaultItem) { if (!isset($defaultItem['name'])) { continue; } $result[] = isset($configMap[$defaultItem['name']]) ? array_merge($defaultItem, ['value' => $configMap[$defaultItem['name']]['value']]) : $defaultItem; } return $result; } /** * 兼容前端用数组、JSON字符串或逗号字符串提交复选框值。 * @param mixed $value * @return array */ private function normalizeVirtualGoodsTypes($value) { if (is_string($value)) { $value = trim($value); $decoded = json_decode($value, true); if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) { $value = $decoded; } elseif ($value === '') { $value = []; } else { $value = explode(',', $value); } } if (!is_array($value)) { return []; } $list = []; foreach ($value as $item) { $item = trim((string)$item); if ($item !== '') { $list[] = $item; } } return array_values(array_unique($list)); } }