where('customer_code', $code)->find()); return $code; } public function generateAppKey(): string { do { $key = 'ak_' . bin2hex(random_bytes(12)); } while (Db::name('enterprise_customer_apps')->where('app_key', $key)->find()); return $key; } public function generateAppSecret(): string { return 'sk_' . bin2hex(random_bytes(24)); } public function encryptSecret(string $secret): string { $key = $this->secretKey(); $iv = random_bytes(16); $cipher = openssl_encrypt($secret, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv); if ($cipher === false) { throw new \RuntimeException('应用密钥加密失败'); } return base64_encode($iv . $cipher); } public function decryptSecret(string $cipherText): string { $raw = base64_decode($cipherText, true); if ($raw === false || strlen($raw) <= 16) { return ''; } $iv = substr($raw, 0, 16); $cipher = substr($raw, 16); $secret = openssl_decrypt($cipher, 'AES-256-CBC', $this->secretKey(), OPENSSL_RAW_DATA, $iv); return is_string($secret) ? $secret : ''; } public function ensureVirtualUser(array $customer): int { $existingUserId = (int)($customer['user_id'] ?? 0); if ($existingUserId > 0 && Db::name('users')->where('id', $existingUserId)->find()) { return $existingUserId; } $now = date('Y-m-d H:i:s'); $mobile = 'ENT' . substr(hash('sha256', (string)($customer['customer_code'] ?? $customer['id'] ?? '')), 0, 20) . '@V'; $userId = (int)Db::name('users')->insertGetId([ 'nickname' => (string)($customer['customer_name'] ?? '大客户'), 'avatar' => '', 'mobile' => $mobile, 'password' => '', 'status' => 'enabled', 'last_login_at' => null, 'created_at' => $now, 'updated_at' => $now, ]); Db::name('enterprise_customers')->where('id', $customer['id'])->update([ 'user_id' => $userId, 'updated_at' => $now, ]); return $userId; } public function formatCustomer(array $item): array { return [ 'id' => (int)$item['id'], 'customer_code' => (string)$item['customer_code'], 'customer_name' => (string)$item['customer_name'], 'contact_name' => (string)($item['contact_name'] ?? ''), 'contact_mobile' => (string)($item['contact_mobile'] ?? ''), 'contact_email' => (string)($item['contact_email'] ?? ''), 'settlement_type' => (string)($item['settlement_type'] ?? 'monthly'), 'settlement_type_text' => '月结', 'user_id' => (int)($item['user_id'] ?? 0), 'webhook_url' => (string)($item['webhook_url'] ?? ''), 'webhook_enabled' => (bool)($item['webhook_enabled'] ?? false), 'status' => (string)($item['status'] ?? 'enabled'), 'status_text' => ($item['status'] ?? 'enabled') === 'enabled' ? '启用中' : '已停用', 'remark' => (string)($item['remark'] ?? ''), 'created_at' => (string)($item['created_at'] ?? ''), 'updated_at' => (string)($item['updated_at'] ?? ''), ]; } public function formatApp(array $item): array { return [ 'id' => (int)$item['id'], 'customer_id' => (int)$item['customer_id'], 'app_name' => (string)($item['app_name'] ?? ''), 'app_key' => (string)$item['app_key'], 'secret_last4' => (string)($item['secret_last4'] ?? ''), 'status' => (string)($item['status'] ?? 'enabled'), 'status_text' => ($item['status'] ?? 'enabled') === 'enabled' ? '启用中' : '已停用', 'last_used_at' => (string)($item['last_used_at'] ?? ''), 'created_at' => (string)($item['created_at'] ?? ''), ]; } private function secretKey(): string { $seed = $_ENV['APP_KEY'] ?? $_ENV['JWT_SECRET'] ?? 'anxinyan-enterprise-secret-key'; return hash('sha256', (string)$seed, true); } }