项目提交

项目全量提交
main
LiJiaWen 4 weeks ago
commit 16294ca927
  1. 54
      .gitignore
  2. 25
      CA-Platform-Linker.sln
  3. 23
      CA-Platform-Linker/CA-Platform-Linker.csproj
  4. 230
      CA-Platform-Linker/Controllers/ClientController.cs
  5. 78
      CA-Platform-Linker/Models/Coss/CossModels.cs
  6. 80
      CA-Platform-Linker/Models/DTO/ClientDto.cs
  7. 24
      CA-Platform-Linker/Models/SignInfo.cs
  8. 66
      CA-Platform-Linker/Program.cs
  9. 30
      CA-Platform-Linker/Properties/launchSettings.json
  10. 272
      CA-Platform-Linker/README.md
  11. 160
      CA-Platform-Linker/Services/ClientService.cs
  12. 16
      CA-Platform-Linker/Services/Interfaces/IClientService.cs
  13. 86
      CA-Platform-Linker/Startup.cs
  14. 68
      CA-Platform-Linker/Tools/ConfigHelper.cs
  15. 93
      CA-Platform-Linker/Tools/CossHelper.cs
  16. 13
      CA-Platform-Linker/Tools/LogHelper.cs
  17. 253
      CA-Platform-Linker/Tools/MySecurity.cs
  18. 30
      CA-Platform-Linker/Tools/Nlog/CallsiteNamespaceLayoutRenderer.cs
  19. 89
      CA-Platform-Linker/Tools/SqlHelper.cs
  20. 9
      CA-Platform-Linker/appsettings.Development.json
  21. 38
      CA-Platform-Linker/appsettings.json
  22. 77
      CA-Platform-Linker/nlog.config

54
.gitignore vendored

@ -0,0 +1,54 @@
# 编译输出目录
[Dd]ebug/
[Rr]elease/
bin/
obj/
# .NET 生成文件
*.cs.user
*.csproj.user
*.suo
*.user
*.userosscache
*.sln.docstates
# Visual Studio
.vs/
*.swp
*.vspx
*.vspscc
*.vssscc
_ReSharper*/
*.ReSharper*
# Rider / JetBrains
.idea/
*.iml
*.iws
*.xml
# VS Code
.vscode/
*.code-workspace
# 日志
logs/
*.log
# 临时文件
*.tmp
*.temp
# 操作系统文件
.DS_Store
Thumbs.db
# dotnet tools 本地安装
.dotnet/
# NuGet
*.nupkg
.nuget/
# 测试覆盖率
coverage/

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.37206.5
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CA-Platform-Linker", "CA-Platform-Linker\CA-Platform-Linker.csproj", "{4907FF24-C349-4A4E-96C0-E48391F3AACA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{4907FF24-C349-4A4E-96C0-E48391F3AACA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4907FF24-C349-4A4E-96C0-E48391F3AACA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4907FF24-C349-4A4E-96C0-E48391F3AACA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4907FF24-C349-4A4E-96C0-E48391F3AACA}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {EB187797-AD1E-4986-8418-9A5EF95767D8}
EndGlobalSection
EndGlobal

@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RootNamespace>CA_Platform_Linker</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.1.5" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
<PackageReference Include="NLog" Version="4.7.15" />
<PackageReference Include="NLog.Web.AspNetCore" Version="4.9.3" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
</ItemGroup>
<ItemGroup>
<Content Update="nlog.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>

@ -0,0 +1,230 @@
using CA_Platform_Linker.Models.Coss;
using CA_Platform_Linker.Models.DTO;
using CA_Platform_Linker.Services.Interfaces;
using CA_Platform_Linker.Tools;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Threading.Tasks;
namespace CA_Platform_Linker.Controllers
{
[Route("[controller]/[action]")]
[ApiController]
public class ClientController : ControllerBase
{
private readonly IClientService _clientService;
public ClientController(IClientService clientService)
{
_clientService = clientService;
}
[HttpPost]
public async Task<IActionResult> Login([FromQuery] string clientType = "LIS")
{
try
{
var result = await _clientService.StartAutoSignAsync(clientType, 3600 * 24);
LogHelper.Log.Info(result.ToString());
if (result.status == "200")
{
return Ok(new ApiLoginResponse
{
Success = true,
Message = "二维码生成成功,请扫码登录",
SignDataId = result.data.signDataId,
QrCode = result.data.qrCode
});
}
else
{
return BadRequest(new ApiLoginResponse
{
Success = false,
Message = $"二维码生成失败: {result.message}"
});
}
}
catch (Exception ex)
{
LogHelper.Log.Error($"二维码生成失败: {ex.Message}");
return BadRequest(new ApiLoginResponse
{
Success = false,
Message = $"二维码生成失败: {ex.Message}"
});
}
}
[HttpPost]
public async Task<IActionResult> AddSignJob([FromBody] ApiSignRequest request, [FromQuery] string clientType = "LIS")
{
return BadRequest(new ApiSignResponse
{
Success = false,
Message = "接口已停用,请使用 AutoSign 接口"
});
try
{
var result = await _clientService.AddSignJobAsync(
clientType,
request.Title,
request.Data,
request.UserId,
request.Algo,
request.ExpiryDate
);
if (result.status == "200")
{
return Ok(new ApiSignResponse
{
Success = true,
Message = "添加签名任务成功",
SignDataId = result.data.signDataId,
QrCode = result.data.qrCode
});
}
else
{
return BadRequest(new ApiSignResponse
{
Success = false,
Message = $"添加签名任务失败: {result.message}"
});
}
}
catch (Exception ex)
{
LogHelper.Log.Error($"添加签名任务失败: {ex.Message}");
return BadRequest(new ApiSignResponse
{
Success = false,
Message = $"添加签名任务失败: {ex.Message}"
});
}
}
[HttpPost]
public async Task<IActionResult> AutoSign([FromBody] ApiAutoSignRequest request, [FromQuery] string clientType = "LIS", [FromQuery] int clientOper = 0)
{
try
{
if (clientOper < 0 || clientOper > 99)
{
return BadRequest(new ApiAutoSignResponse
{
Success = false,
Message = "clientOper 参数值必须在 0-99 范围内"
});
}
var result = await _clientService.AutoSignAsync(
clientType,
request.UserId,
request.SignToken,
request.Data,
request.Algo,
request.ExpiryDate,
request.MZNum,
request.ZYNum,
request.SignID,
clientOper
);
if (result.status == "200")
{
return Ok(new ApiAutoSignResponse
{
Success = true,
Message = "自动签名成功",
SignResult = result.data.signResult,
SignCert = result.data.signCert,
SignDataId = result.data.signDataId
});
}
else
{
LogHelper.Log.Error($"自动签名失败: {result.message}");
return BadRequest(new ApiAutoSignResponse
{
Success = false,
Message = $"自动签名失败: {result.message}"
});
}
}
catch (Exception ex)
{
LogHelper.Log.Error($"自动签名失败: {ex.Message}");
return BadRequest(new ApiAutoSignResponse
{
Success = false,
Message = $"自动签名失败: {ex.Message}"
});
}
}
[HttpPost]
public async Task<IActionResult> GetSignResult([FromBody] ApiGetSignResultRequest request, [FromQuery] string clientType = "LIS")
{
try
{
var result = await _clientService.GetSignResultAsync(clientType, request.SignDataId);
if (result.status == "200")
{
string message = "查询中";
bool isLoginSuccess = false;
if (result.data.jobStatus == "FINISH")
{
message = "登录成功";
isLoginSuccess = true;
}
else if (result.data.jobStatus == "PROCESSING")
{
message = "等待扫码";
}
else if (result.data.jobStatus == "FAIL")
{
message = "签名失败";
}
else if (result.data.jobStatus == "TIMEOUT")
{
message = "登录超时";
}
return Ok(new ApiGetSignResultResponse
{
Success = true,
Message = message,
JobStatus = result.data.jobStatus,
SignResult = result.data.signResult,
SignCert = result.data.signCert,
UserId = result.data.msspId,
IsLoginSuccess = isLoginSuccess
});
}
else
{
return BadRequest(new ApiGetSignResultResponse
{
Success = false,
Message = $"获取签名结果失败: {result.message}"
});
}
}
catch (Exception ex)
{
LogHelper.Log.Error($"获取签名结果失败: {ex.Message}");
return BadRequest(new ApiGetSignResultResponse
{
Success = false,
Message = $"获取签名结果失败: {ex.Message}"
});
}
}
}
}

@ -0,0 +1,78 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace CA_Platform_Linker.Models.Coss
{
public class CossBaseRequest
{
public string version { get; set; }
public string appId { get; set; }
public string signAlgo { get; set; }
public string signature { get; set; }
}
public class CossResponse<T>
{
public string status { get; set; }
public string message { get; set; }
public T data { get; set; }
}
public class CossResultData
{
public string signDataId { get; set; }
public string qrCode { get; set; }
public string jobStatus { get; set; }
public string msspId { get; set; }
public string signCert { get; set; }
public string signResult { get; set; }
public string image { get; set; }
public string tsResp { get; set; }
}
public class StartAutoSignRequest : CossBaseRequest
{
public string timeRegion { get; set; }
}
public class AddSignJobRequest : CossBaseRequest
{
public string title { get; set; }
public string userId { get; set; }
public string dataType { get; set; }
public string algo { get; set; }
public string description { get; set; }
public string data { get; set; }
public string expiryDate { get; set; }
}
public class AutoSignRequest : CossBaseRequest
{
public string userId { get; set; }
public string title { get; set; }
public string dataType { get; set; }
public string algo { get; set; }
public string description { get; set; }
public string data { get; set; }
public string signToken { get; set; }
public string expiryDate { get; set; }
}
public class GetSignResultRequest : CossBaseRequest
{
public string signDataId { get; set; }
}
public class QueryImageRequest : CossBaseRequest
{
public string userId { get; set; }
}
public class CreateTssRequest : CossBaseRequest
{
public string oriData { get; set; }
public string attachCert { get; set; }
}
}

@ -0,0 +1,80 @@
using System.ComponentModel.DataAnnotations;
namespace CA_Platform_Linker.Models.DTO
{
public class ApiLoginResponse
{
public bool Success { get; set; }
public string Message { get; set; }
public string SignDataId { get; set; }
public string QrCode { get; set; }
}
public class ApiSignRequest
{
[Required(ErrorMessage = "标题不能为空")]
public string Title { get; set; }
[Required(ErrorMessage = "数据不能为空")]
public string Data { get; set; }
public string UserId { get; set; }
public string Algo { get; set; } = "SM3withSM2";
public string ExpiryDate { get; set; } = "1400";
}
public class ApiSignResponse
{
public bool Success { get; set; }
public string Message { get; set; }
public string SignDataId { get; set; }
public string QrCode { get; set; }
public string SignResult { get; set; }
public string SignCert { get; set; }
}
public class ApiAutoSignRequest
{
[Required(ErrorMessage = "用户ID不能为空")]
public string UserId { get; set; }
[Required(ErrorMessage = "签名令牌不能为空")]
public string SignToken { get; set; }
[Required(ErrorMessage = "数据不能为空")]
public string Data { get; set; }
public string Algo { get; set; } = "SM3withSM2";
public string ExpiryDate { get; set; } = "1400";
public int MZNum { get; set; } = 0;
public int ZYNum { get; set; } = 0;
public string SignID { get; set; } = string.Empty;
}
public class ApiAutoSignResponse
{
public bool Success { get; set; }
public string Message { get; set; }
public string SignResult { get; set; }
public string SignCert { get; set; }
public string SignDataId { get; set; }
}
public class ApiGetSignResultRequest
{
[Required(ErrorMessage = "签名数据ID不能为空")]
public string SignDataId { get; set; }
}
public class ApiGetSignResultResponse
{
public bool Success { get; set; }
public string Message { get; set; }
public string JobStatus { get; set; }
public string SignResult { get; set; }
public string SignCert { get; set; }
public string UserId { get; set; }
public bool IsLoginSuccess { get; set; }
}
}

@ -0,0 +1,24 @@
using System;
namespace CA_Platform_Linker.Models
{
public class SignInfo
{
public long KeyNo { get; set; }
public int TextType { get; set; }
public int MZNum { get; set; }
public int ZYNum { get; set; }
public string SourceText { get; set; }
public string Base64Text { get; set; }
public string OperCode { get; set; }
public string OperName { get; set; }
public string SignDate { get; set; }
public string CertID { get; set; }
public string OperCert { get; set; }
public string SignData { get; set; }
public string TSData { get; set; }
public string SignID { get; set; }
public string OperType { get; set; }
public int SignWay { get; set; }
}
}

@ -0,0 +1,66 @@
using CA_Platform_Linker.Tools;
using CA_Platform_Linker.Tools.Nlog;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using NLog.LayoutRenderers;
using NLog.Web;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace CA_Platform_Linker
{
public class Program
{
public static void Main(string[] args)
{
#region ע<EFBFBD><EFBFBD>Nlog<EFBFBD>Զ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ⱦ<EFBFBD><EFBFBD>
LayoutRenderer.Register<CallsiteNamespaceLayoutRenderer>("callsite-namespace");
#endregion
//var logger = NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger(); // Nlog<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD>
try
{
LogHelper.Log.Info("===========program initialization===============");
JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
};
CreateHostBuilder(args).Build().Run();
}
catch (Exception exception)
{
// Nlog<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><EFBFBD><EFBFBD>
LogHelper.Log.Error(exception, "Stopped program because of exception");
throw;
}
finally
{
// ȷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD>ó<EFBFBD><EFBFBD><EFBFBD><EFBFBD>˳<EFBFBD>ǰˢ<EFBFBD>º<EFBFBD>ֹͣ<EFBFBD>ڲ<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>/<EFBFBD>̣߳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Linux<EFBFBD>ϵķֶι<EFBFBD><EFBFBD>ϣ<EFBFBD>
NLog.LogManager.Shutdown();
}
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.ConfigureLogging(logging =>
{
//logging.ClearProviders(); // <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>п<EFBFBD><EFBFBD><EFBFBD>̨<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <EFBFBD><EFBFBD>־<EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̨<EFBFBD><EFBFBD>־<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>
logging.AddConsole(c => c.TimestampFormat = "<EFBFBD><EFBFBD>yyyy-MM-dd HH:mm:ss<EFBFBD><EFBFBD>");
logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace).AddConsole(); // <EFBFBD><EFBFBD><EFBFBD><EFBFBD>̨<EFBFBD><EFBFBD>־<EFBFBD><EFBFBD><EFBFBD>
})
.UseNLog(); //<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>־<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Nlog;
}
}

@ -0,0 +1,30 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:5000",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"CA_Platform_Linker": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

@ -0,0 +1,272 @@
# CA平台链接器服务
这是一个客户端程序和CA服务中间的信息交互服务,提供登录验证、自动签名开启和字符串签名功能。
## 功能特性
1. **登录验证** - 支持扫码登录
2. **自动签名开启** - 开启自动签名功能
3. **字符串签名** - 支持多种签名方式
4. **Base64编码/解码** - 提供数据转换工具
5. **时间戳服务** - 创建时间戳
## API接口
### 1. 登录验证
**接口**: `POST /Client/Login`
**请求体**:
```json
{
"account": "test",
"password": "123456"
}
```
**响应**:
```json
{
"success": true,
"message": "登录成功,请扫码",
"signDataId": "xxx",
"qrCode": "xxx"
}
```
### 2. 添加签名任务
**接口**: `POST /Client/AddSignJob`
**请求体**:
```json
{
"title": "测试签名",
"data": "要签名的数据",
"userId": "用户ID(可选)",
"algo": "SM3withSM2",
"expiryDate": "1400"
}
```
**响应**:
```json
{
"success": true,
"message": "添加签名任务成功",
"signDataId": "xxx",
"qrCode": "xxx"
}
```
### 3. 自动签名
**接口**: `POST /Client/AutoSign`
**请求体**:
```json
{
"userId": "用户ID",
"signToken": "签名令牌",
"data": "要签名的数据",
"algo": "SM3withSM2",
"expiryDate": "1400"
}
```
**响应**:
```json
{
"success": true,
"message": "自动签名成功",
"signResult": "签名结果",
"signCert": "签名证书",
"signDataId": "xxx"
}
```
### 4. 获取签名结果
**接口**: `POST /Client/GetSignResult`
**请求体**:
```json
{
"signDataId": "签名数据ID"
}
```
**响应**:
```json
{
"success": true,
"message": "获取签名结果成功",
"jobStatus": "FINISH",
"signResult": "签名结果",
"signCert": "签名证书",
"userId": "用户ID"
}
```
### 5. 查询签名图片
**接口**: `POST /Client/QueryImage`
**请求体**: `"用户ID"`
**响应**:
```json
{
"success": true,
"message": "查询签名图片成功",
"image": "base64图片数据"
}
```
### 6. Base64编码
**接口**: `POST /Client/Base64Encode`
**请求体**:
```json
{
"plainText": "要编码的文本"
}
```
**响应**:
```json
{
"success": true,
"message": "Base64编码成功",
"base64Data": "编码后的数据"
}
```
### 7. Base64解码
**接口**: `POST /Client/Base64Decode`
**请求体**:
```json
{
"base64Data": "要解码的Base64数据"
}
```
**响应**:
```json
{
"success": true,
"message": "Base64解码成功",
"plainText": "解码后的文本"
}
```
### 8. 创建时间戳
**接口**: `POST /Client/CreateTss`
**请求体**:
```json
{
"oriData": "原文数据",
"attachCert": true
}
```
**响应**:
```json
{
"success": true,
"message": "创建时间戳成功",
"tsResp": "时间戳响应"
}
```
## 配置说明
`appsettings.json` 中配置CA服务相关参数:
```json
{
"CossBaseUrl": "https://newcoss-dev.isignet.cn:10201/coss/service/v1/",
"CossAppId": "APP_7B3F36A14E99410A80B37AEF332E3247",
"CossSecureCode": "DLwiH46Esb8ccNTkuSSVAadNTWUfW0sc",
"CossSignAlgo": "HMAC",
"CossVersion": "1.0"
}
```
## 使用示例
### 1. 启动服务
```bash
dotnet run
```
### 2. 访问Swagger文档
打开浏览器访问: `http://localhost:5000/LISPlatformLinker/swagger`
### 3. 调用API示例
#### 登录并获取二维码
```bash
curl -X POST "http://localhost:5000/LISPlatformLinker/Client/Login" \
-H "Content-Type: application/json" \
-d '{"account":"test","password":"123456"}'
```
#### 添加签名任务
```bash
curl -X POST "http://localhost:5000/LISPlatformLinker/Client/AddSignJob" \
-H "Content-Type: application/json" \
-d '{"title":"测试签名","data":"Hello World","algo":"SM3withSM2"}'
```
#### 自动签名
```bash
curl -X POST "http://localhost:5000/LISPlatformLinker/Client/AutoSign" \
-H "Content-Type: application/json" \
-d '{"userId":"xxx","signToken":"xxx","data":"Hello World"}'
```
## 项目结构
```
CA-Platform-Linker/
├── Controllers/
│ └── ClientController.cs # 客户端控制器
├── Models/
│ ├── Coss/
│ │ └── CossModels.cs # CA服务模型
│ └── DTO/
│ └── ClientDto.cs # 客户端DTO
├── Services/
│ ├── Interfaces/
│ │ └── IClientService.cs # 客户端服务接口
│ └── ClientService.cs # 客户端服务实现
├── Tools/
│ ├── CossHelper.cs # CA服务帮助类
│ ├── ConfigHelper.cs # 配置帮助类
│ └── MySecurity.cs # 安全类
└── appsettings.json # 配置文件
```
## 注意事项
1. 所有接口都使用POST方法
2. 请求和响应都使用JSON格式
3. 签名数据会自动进行Base64编码
4. 需要正确配置CA服务的连接参数
5. 建议在生产环境中使用HTTPS协议
## 错误处理
所有接口都包含错误处理,当请求失败时会返回错误信息:
```json
{
"success": false,
"message": "错误描述"
}
```
## 日志
使用NLog进行日志记录,日志文件位于 `logs/` 目录下:
- `logs/info/` - 信息日志
- `logs/error/` - 错误日志
- `logs/debug/` - 调试日志

@ -0,0 +1,160 @@
using CA_Platform_Linker.Models;
using CA_Platform_Linker.Models.Coss;
using CA_Platform_Linker.Services.Interfaces;
using CA_Platform_Linker.Tools;
using CA_Platform_Linker.Tools.Nlog;
using System;
using System.Collections;
using System.Threading.Tasks;
namespace CA_Platform_Linker.Services
{
public class ClientService : IClientService
{
public async Task<CossResponse<CossResultData>> StartAutoSignAsync(string clientType, int timeRegion = 3600 * 24)
{
try
{
Hashtable ht = CossHelper.BuildBaseHashtable(clientType);
ht.Add("timeRegion", timeRegion.ToString());
return await CossHelper.PostAsync<CossResultData>("startAutoSign", ht, clientType);
}
catch (Exception ex)
{
LogHelper.Log.Error($"开启自动签名失败: {ex.Message}");
return new CossResponse<CossResultData>
{
status = "500",
message = ex.Message
};
}
}
public async Task<CossResponse<CossResultData>> AddSignJobAsync(string clientType, string title, string data, string userId = "", string algo = "SM3withSM2", string expiryDate = "1400")
{
try
{
string base64Data = data;
if (!string.IsNullOrEmpty(data))
{
base64Data = CossHelper.Base64Encode(data);
}
Hashtable ht = CossHelper.BuildBaseHashtable(clientType);
ht.Add("title", title);
ht.Add("dataType", "DATA");
ht.Add("algo", algo);
ht.Add("description", clientType + "签名任务");
ht.Add("data", base64Data);
ht.Add("expiryDate", expiryDate);
if (!string.IsNullOrEmpty(userId))
{
ht.Add("userId", userId);
}
return await CossHelper.PostAsync<CossResultData>("addSignJob", ht, clientType);
}
catch (Exception ex)
{
LogHelper.Log.Error($"添加签名任务失败: {ex.Message}");
return new CossResponse<CossResultData>
{
status = "500",
message = ex.Message
};
}
}
public async Task<CossResponse<CossResultData>> AutoSignAsync(string clientType, string userId, string signToken, string data, string algo = "SM3withSM2", string expiryDate = "1400", int mzNum = 0, int zyNum = 0, string signID = "", int clientOper = 0)
{
try
{
string base64Data = data;
if (!string.IsNullOrEmpty(data))
{
base64Data = CossHelper.Base64Encode(data);
}
Hashtable ht = CossHelper.BuildBaseHashtable(clientType);
ht.Add("userId", userId);
ht.Add("title", clientType + "自动签名");
ht.Add("dataType", "DATA");
ht.Add("algo", algo);
ht.Add("description", clientType + "自动签名");
ht.Add("data", base64Data);
ht.Add("signToken", signToken);
ht.Add("expiryDate", expiryDate);
var result = await CossHelper.PostAsync<CossResultData>("autoSign", ht, clientType);
if (result.status == "200")
{
_ = Task.Run(() =>
{
try
{
var clientConfig = ConfigHelper.GetCossClientConfig(clientType);
var (operCode, operName) = SqlHelper.GetOperatorInfo(userId);
var signInfo = new SignInfo
{
TextType = clientConfig.TextType + clientOper,
MZNum = mzNum,
ZYNum = zyNum,
SourceText = data,
Base64Text = "",
OperCode = operCode ?? "",
OperName = operName ?? "",
SignDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
CertID = "",
OperCert = result.data.signCert,
SignData = result.data.signResult,
TSData = "",
SignID = signID,
OperType = clientType + "自动签名",
SignWay = 1
};
SqlHelper.InsertSignInfo(signInfo);
LogHelper.Log.Info($"签名记录已写入数据库,SignDataId: {result.data.signDataId}");
}
catch (Exception ex)
{
LogHelper.Log.Error($"写入签名记录失败:{ex.Message}");
}
});
}
return result;
}
catch (Exception ex)
{
LogHelper.Log.Error($"自动签名失败: {ex.Message}");
return new CossResponse<CossResultData>
{
status = "500",
message = ex.Message
};
}
}
public async Task<CossResponse<CossResultData>> GetSignResultAsync(string clientType, string signDataId)
{
try
{
Hashtable ht = CossHelper.BuildBaseHashtable(clientType);
ht.Add("signDataId", signDataId);
return await CossHelper.PostAsync<CossResultData>("getSignResult", ht, clientType);
}
catch (Exception ex)
{
LogHelper.Log.Error($"获取签名结果失败: {ex.Message}");
return new CossResponse<CossResultData>
{
status = "500",
message = ex.Message
};
}
}
}
}

@ -0,0 +1,16 @@
using CA_Platform_Linker.Models.Coss;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace CA_Platform_Linker.Services.Interfaces
{
public interface IClientService
{
Task<CossResponse<CossResultData>> StartAutoSignAsync(string clientType, int timeRegion = 3600 * 24);
Task<CossResponse<CossResultData>> AddSignJobAsync(string clientType, string title, string data, string userId = "", string algo = "SM3withSM2", string expiryDate = "1400");
Task<CossResponse<CossResultData>> AutoSignAsync(string clientType, string userId, string signToken, string data, string algo = "SM3withSM2", string expiryDate = "1400", int mzNum = 0, int zyNum = 0, string signID = "", int clientOper = 0);
Task<CossResponse<CossResultData>> GetSignResultAsync(string clientType, string signDataId);
}
}

@ -0,0 +1,86 @@
using CA_Platform_Linker.Services;
using CA_Platform_Linker.Services.Interfaces;
using CA_Platform_Linker.Tools;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace CA_Platform_Linker
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
//读取配置
ConfigHelper.Initialize(Configuration);
//初始化数据库连接
SqlHelper.Initialize(Configuration);
services.AddControllers();
//注册服务
services.AddTransient<IClientService, ClientService>();
services.AddSwaggerGen(s =>
{
//标记swagger 信息(内容自定义)
//V1.0.0-->SwaggerEndpoint(url,name)-->url 使用
s.SwaggerDoc("V1.0.0", new Microsoft.OpenApi.Models.OpenApiInfo
{
Title = "CA平台连接服务",
Version = "1.0.0",
});
s.AddServer(new OpenApiServer
{
Url = "/CAPlatformLinker",
Description = "API全局路由"
});
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UsePathBase("/CAPlatformLinker");
app.UseSwagger();
app.UseSwaggerUI(su =>
{
//url中[V1.0.0]与ConfigureServices 中配置的SwaggerDoc("V1.0.0",..) 保持一致
su.SwaggerEndpoint("/swagger/V1.0.0/swagger.json", null);
});
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}

@ -0,0 +1,68 @@
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace CA_Platform_Linker.Tools
{
public static class ConfigHelper
{
private static IConfiguration _config;
public static void Initialize(IConfiguration configuration)
{
_config = configuration;
}
// LIS数据库连接字符串
public static string ConnectionString => MySecurity.SDecryptString(_config.GetValue<string>("ConnectionString"));
// 检验平台接口地址
public static string PlatformUrl => _config.GetValue<string>("PlatformUrl");
// 医疗机构代码
public static string HospitalCode => _config.GetValue<string>("HospitalCode");
// 医疗机构名称
public static string HospitalName => _config.GetValue<string>("HospitalName");
// CA服务基础配置
public static string CossBaseUrl => _config.GetValue<string>("CossBaseUrl", "http://192.168.0.148:10201/coss/service/v1/");
public static string CossSignAlgo => _config.GetValue<string>("CossSignAlgo", "HMAC");
public static string CossVersion => _config.GetValue<string>("CossVersion", "1.0");
// 获取指定客户端的配置
public static CossClientConfig GetCossClientConfig(string clientType)
{
var clientsSection = _config.GetSection("CossClients");
var clientSection = clientsSection.GetSection(clientType);
if (!clientSection.Exists())
{
throw new ArgumentException($"未找到客户端类型 '{clientType}' 的配置");
}
return new CossClientConfig
{
AppId = clientSection.GetValue<string>("AppId"),
SecureCode = clientSection.GetValue<string>("SecureCode"),
TextType = clientSection.GetValue<int>("TextType", 0)
};
}
// 获取所有支持的客户端类型
public static List<string> GetSupportedClientTypes()
{
var clientsSection = _config.GetSection("CossClients");
return clientsSection.GetChildren().Select(x => x.Key).ToList();
}
}
public class CossClientConfig
{
public string AppId { get; set; }
public string SecureCode { get; set; }
public int TextType { get; set; }
}
}

@ -0,0 +1,93 @@
using CA_Platform_Linker.Models.Coss;
using CA_Platform_Linker.Tools;
using CA_Platform_Linker.Tools.Nlog;
using Newtonsoft.Json;
using System;
using System.Collections;
using System.Linq;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace CA_Platform_Linker.Tools
{
public class CossHelper
{
private static readonly HttpClient _httpClient = new HttpClient();
public static string GetSignature(string secret, string content)
{
secret = secret ?? "";
var encoding = Encoding.UTF8;
byte[] keyByte = encoding.GetBytes(secret);
byte[] messageBytes = encoding.GetBytes(content);
using (var hmacsha256 = new HMACSHA256(keyByte))
{
byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
return Convert.ToBase64String(hashmessage);
}
}
public static string GetSignatureValue(Hashtable ht, string secureCode)
{
string str = "";
ArrayList akeys = new ArrayList(ht.Keys);
akeys.Sort();
foreach (string key in akeys)
{
str += key + "=" + ht[key] + "&";
}
str = str.Substring(0, str.Length - 1);
return GetSignature(secureCode, str);
}
public static Hashtable BuildBaseHashtable(string clientType)
{
var clientConfig = ConfigHelper.GetCossClientConfig(clientType);
Hashtable ht = new Hashtable();
ht.Add("version", ConfigHelper.CossVersion);
ht.Add("appId", clientConfig.AppId);
ht.Add("signAlgo", ConfigHelper.CossSignAlgo);
return ht;
}
public static async Task<CossResponse<T>> PostAsync<T>(string apiName, Hashtable ht, string clientType)
{
try
{
var clientConfig = ConfigHelper.GetCossClientConfig(clientType);
ht.Add("signature", GetSignatureValue(ht, clientConfig.SecureCode));
string strJson = JsonConvert.SerializeObject(ht);
string url = ConfigHelper.CossBaseUrl + apiName;
var content = new StringContent(strJson, Encoding.UTF8, "application/json");
var response = await _httpClient.PostAsync(url, content);
string responseStr = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<CossResponse<T>>(responseStr);
}
catch (Exception ex)
{
LogHelper.Log.Error($"CA服务调用失败: {ex.Message}");
return new CossResponse<T>
{
status = "500",
message = ex.Message
};
}
}
public static string Base64Encode(string plainText)
{
var plainTextBytes = Encoding.UTF8.GetBytes(plainText);
return Convert.ToBase64String(plainTextBytes);
}
public static string Base64Decode(string base64EncodedData)
{
var base64EncodedBytes = Convert.FromBase64String(base64EncodedData);
return Encoding.UTF8.GetString(base64EncodedBytes);
}
}
}

@ -0,0 +1,13 @@
using NLog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace CA_Platform_Linker.Tools
{
public class LogHelper
{
public static readonly NLog.Logger Log = LogManager.GetCurrentClassLogger();
}
}

@ -0,0 +1,253 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace CA_Platform_Linker.Tools
{
/// <summary>
/// MySecurity(安全类) 的摘要说明。
/// </summary>
public class MySecurity
{
/// <summary>
/// 初始化安全类
/// </summary>
public MySecurity()
{
///默认密码
key = "peis77911@*71";
}
private string key; //默认密钥
private byte[] sKey;
private byte[] sIV;
#region 加密字符串
/// <summary>
/// 加密字符串
/// </summary>
/// <param name="inputStr">输入字符串</param>
/// <param name="keyStr">密码,可以为“”</param>
/// <returns>输出加密后字符串</returns>
static public string SEncryptString(string inputStr, string keyStr)
{
MySecurity ws = new MySecurity();
return ws.EncryptString(inputStr, keyStr);
}
/// <summary>
/// 加密字符串
/// </summary>
/// <param name="inputStr">输入字符串</param>
/// <param name="keyStr">密码,可以为“”</param>
/// <returns>输出加密后字符串</returns>
public string EncryptString(string inputStr, string keyStr)
{
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
if (keyStr == "")
keyStr = key;
byte[] inputByteArray = Encoding.Default.GetBytes(inputStr);
byte[] keyByteArray = Encoding.Default.GetBytes(keyStr);
SHA1 ha = new SHA1Managed();
byte[] hb = ha.ComputeHash(keyByteArray);
sKey = new byte[8];
sIV = new byte[8];
for (int i = 0; i < 8; i++)
sKey[i] = hb[i];
for (int i = 8; i < 16; i++)
sIV[i - 8] = hb[i];
des.Key = sKey;
des.IV = sIV;
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
cs.Write(inputByteArray, 0, inputByteArray.Length);
cs.FlushFinalBlock();
StringBuilder ret = new StringBuilder();
foreach (byte b in ms.ToArray())
{
ret.AppendFormat("{0:X2}", b);
}
cs.Close();
ms.Close();
return ret.ToString();
}
#endregion 加密字符串
#region 加密字符串 密钥为系统默认 0123456789
/// <summary>
/// 加密字符串 密钥为系统默认
/// </summary>
/// <param name="inputStr">输入字符串</param>
/// <returns>输出加密后字符串</returns>
static public string SEncryptString(string inputStr)
{
MySecurity ws = new MySecurity();
return ws.EncryptString(inputStr, "");
}
#endregion 加密字符串 密钥为系统默认 0123456789
#region 加密文件
/// <summary>
/// 加密文件
/// </summary>
/// <param name="filePath">输入文件路径</param>
/// <param name="savePath">加密后输出文件路径</param>
/// <param name="keyStr">密码,可以为“”</param>
/// <returns></returns>
public bool EncryptFile(string filePath, string savePath, string keyStr)
{
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
if (keyStr == "")
keyStr = key;
FileStream fs = File.OpenRead(filePath);
byte[] inputByteArray = new byte[fs.Length];
fs.Read(inputByteArray, 0, (int)fs.Length);
fs.Close();
byte[] keyByteArray = Encoding.Default.GetBytes(keyStr);
SHA1 ha = new SHA1Managed();
byte[] hb = ha.ComputeHash(keyByteArray);
sKey = new byte[8];
sIV = new byte[8];
for (int i = 0; i < 8; i++)
sKey[i] = hb[i];
for (int i = 8; i < 16; i++)
sIV[i - 8] = hb[i];
des.Key = sKey;
des.IV = sIV;
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
cs.Write(inputByteArray, 0, inputByteArray.Length);
cs.FlushFinalBlock();
fs = File.OpenWrite(savePath);
foreach (byte b in ms.ToArray())
{
fs.WriteByte(b);
}
fs.Close();
cs.Close();
ms.Close();
return true;
}
#endregion 加密文件
#region 解密字符串
/// <summary>
/// 解密字符串
/// </summary>
/// <param name="inputStr">要解密的字符串</param>
/// <param name="keyStr">密钥</param>
/// <returns>解密后的结果</returns>
static public string SDecryptString(string inputStr, string keyStr)
{
MySecurity ws = new MySecurity();
return ws.DecryptString(inputStr, keyStr);
}
/// <summary>
/// 解密字符串 密钥为系统默认
/// </summary>
/// <param name="inputStr">要解密的字符串</param>
/// <returns>解密后的结果</returns>
static public string SDecryptString(string inputStr)
{
MySecurity ws = new MySecurity();
return ws.DecryptString(inputStr, "");
}
/// <summary>
/// 解密字符串
/// </summary>
/// <param name="inputStr">要解密的字符串</param>
/// <param name="keyStr">密钥</param>
/// <returns>解密后的结果</returns>
public string DecryptString(string inputStr, string keyStr)
{
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
if (keyStr == "")
keyStr = key;
byte[] inputByteArray = new byte[inputStr.Length / 2];
for (int x = 0; x < inputStr.Length / 2; x++)
{
int i = (Convert.ToInt32(inputStr.Substring(x * 2, 2), 16));
inputByteArray[x] = (byte)i;
}
byte[] keyByteArray = Encoding.Default.GetBytes(keyStr);
SHA1 ha = new SHA1Managed();
byte[] hb = ha.ComputeHash(keyByteArray);
sKey = new byte[8];
sIV = new byte[8];
for (int i = 0; i < 8; i++)
sKey[i] = hb[i];
for (int i = 8; i < 16; i++)
sIV[i - 8] = hb[i];
des.Key = sKey;
des.IV = sIV;
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);
cs.Write(inputByteArray, 0, inputByteArray.Length);
cs.FlushFinalBlock();
StringBuilder ret = new StringBuilder();
return System.Text.Encoding.Default.GetString(ms.ToArray());
}
#endregion 解密字符串
#region 解密文件
/// <summary>
/// 解密文件
/// </summary>
/// <param name="filePath">输入文件路径</param>
/// <param name="savePath">解密后输出文件路径</param>
/// <param name="keyStr">密码,可以为“”</param>
/// <returns></returns>
public bool DecryptFile(string filePath, string savePath, string keyStr)
{
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
if (keyStr == "")
keyStr = key;
FileStream fs = File.OpenRead(filePath);
byte[] inputByteArray = new byte[fs.Length];
fs.Read(inputByteArray, 0, (int)fs.Length);
fs.Close();
byte[] keyByteArray = Encoding.Default.GetBytes(keyStr);
SHA1 ha = new SHA1Managed();
byte[] hb = ha.ComputeHash(keyByteArray);
sKey = new byte[8];
sIV = new byte[8];
for (int i = 0; i < 8; i++)
sKey[i] = hb[i];
for (int i = 8; i < 16; i++)
sIV[i - 8] = hb[i];
des.Key = sKey;
des.IV = sIV;
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);
cs.Write(inputByteArray, 0, inputByteArray.Length);
cs.FlushFinalBlock();
fs = File.OpenWrite(savePath);
foreach (byte b in ms.ToArray())
{
fs.WriteByte(b);
}
fs.Close();
cs.Close();
ms.Close();
return true;
}
#endregion 解密文件
}
}

@ -0,0 +1,30 @@
using NLog;
using NLog.LayoutRenderers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CA_Platform_Linker.Tools.Nlog
{
/// <summary>
/// Nlog 日志调用方命名空间名称
/// </summary>
[LayoutRenderer("callsite-namespace")]
public class CallsiteNamespaceLayoutRenderer : LayoutRenderer
{
protected override void Append(StringBuilder builder, LogEventInfo logEvent)
{
if (logEvent != null && !string.IsNullOrEmpty(logEvent.CallerClassName) && logEvent.CallerClassName.Contains("."))
{
// 获取命名空间(如果类型在命名空间中)
var namespaceName = logEvent.CallerClassName.ToString().Split(".")[0];
if (!string.IsNullOrEmpty(namespaceName))
{
builder.Append(namespaceName);
}
}
}
}
}

@ -0,0 +1,89 @@
using CA_Platform_Linker.Models;
using Microsoft.Data.SqlClient;
using Microsoft.Extensions.Configuration;
using System;
namespace CA_Platform_Linker.Tools
{
public static class SqlHelper
{
private static string _connectionString;
public static void Initialize(IConfiguration configuration)
{
_connectionString = configuration.GetConnectionString("HisDB");
}
public static int InsertSignInfo(SignInfo signInfo)
{
if (string.IsNullOrEmpty(_connectionString))
{
throw new InvalidOperationException("数据库连接字符串未配置");
}
string sql = @"INSERT INTO [DigitalSignData].[dbo].[SignInfo]
([TextType], [MZNum], [ZYNum], [SourceText], [Base64Text],
[OperCode], [OperName], [SignDate], [CertID], [OperCert],
[SignData], [TSData], [SignID], [OperType], [SignWay])
VALUES
(@TextType, @MZNum, @ZYNum, @SourceText, @Base64Text,
@OperCode, @OperName, @SignDate, @CertID, @OperCert,
@SignData, @TSData, @SignID, @OperType, @SignWay)";
using (SqlConnection conn = new SqlConnection(_connectionString))
{
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.AddWithValue("@TextType", signInfo.TextType);
cmd.Parameters.AddWithValue("@MZNum", signInfo.MZNum);
cmd.Parameters.AddWithValue("@ZYNum", signInfo.ZYNum);
cmd.Parameters.AddWithValue("@SourceText", (object)signInfo.SourceText ?? DBNull.Value);
cmd.Parameters.AddWithValue("@Base64Text", (object)signInfo.Base64Text ?? DBNull.Value);
cmd.Parameters.AddWithValue("@OperCode", (object)signInfo.OperCode ?? DBNull.Value);
cmd.Parameters.AddWithValue("@OperName", (object)signInfo.OperName ?? DBNull.Value);
cmd.Parameters.AddWithValue("@SignDate", (object)signInfo.SignDate ?? DBNull.Value);
cmd.Parameters.AddWithValue("@CertID", (object)signInfo.CertID ?? DBNull.Value);
cmd.Parameters.AddWithValue("@OperCert", (object)signInfo.OperCert ?? DBNull.Value);
cmd.Parameters.AddWithValue("@SignData", (object)signInfo.SignData ?? DBNull.Value);
cmd.Parameters.AddWithValue("@TSData", (object)signInfo.TSData ?? DBNull.Value);
cmd.Parameters.AddWithValue("@SignID", (object)signInfo.SignID ?? DBNull.Value);
cmd.Parameters.AddWithValue("@OperType", (object)signInfo.OperType ?? DBNull.Value);
cmd.Parameters.AddWithValue("@SignWay", signInfo.SignWay);
conn.Open();
return cmd.ExecuteNonQuery();
}
}
}
public static (string operCode, string operName) GetOperatorInfo(string bjcaMsspid)
{
if (string.IsNullOrEmpty(_connectionString))
{
throw new InvalidOperationException("数据库连接字符串未配置");
}
string sql = @"SELECT [CODE], [NAME]
FROM [HisData].[dbo].[YSCODE]
WHERE [BJCA_MSSPID] = @BJCA_MSSPID";
using (SqlConnection conn = new SqlConnection(_connectionString))
{
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.AddWithValue("@BJCA_MSSPID", bjcaMsspid);
conn.Open();
using (var reader = cmd.ExecuteReader())
{
if (reader.Read())
{
return (reader["CODE"].ToString(), reader["NAME"].ToString());
}
}
}
}
return (null, null);
}
}
}

@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}

@ -0,0 +1,38 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"HisDB": "Data Source=192.168.0.222;User ID=XBDLisUser;Password=BlueFlag.Lis!@#;TrustServerCertificate=True"
},
"CossBaseUrl": "http://192.168.0.148:10201/coss/service/v1/",
"CossSignAlgo": "HMAC",
"CossVersion": "1.0",
"CossClients": {
"LIS": {
"AppId": "APP_E559E1B8906045D4881D74F29361F6BB",
"SecureCode": "MGI0ODQ0NjYxZjg1NDgzZDhkMDNjYzI5YTM4MDA0ZDk=",
"TextType": 500
},
"PEIS": {
"AppId": "APP_6E254EA9538743088BD393C3D0212617",
"SecureCode": "OTdhMDRkMmY1YzVmNDczY2FlZjhhOWE5NmY1OTI2MzY=",
"TextType": 700
},
"Blood": {
"AppId": "APP_855883154E16433EBE12B8C73822AE17",
"SecureCode": "YjI1YjVkYTQ5OWMwNDYxOTkwY2MwZTUyYTkxMzc2MWU=",
"TextType": 600
},
"WeChat": {
"AppId": "APP_E56656ADD9DE48779F21D9FE50529E3A",
"SecureCode": "OTczNzkyMWNlMzk2NGE3YjgyMTdkMzRkNzBmODllNTk=",
"TextType": 800
}
}
}

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="utf-8"?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
internalLogLevel="Info">
<!-- 启用.net core的核心布局渲染器 -->
<extensions>
<add assembly="NLog.Web.AspNetCore" />
<add assembly="PeisReserve.Helper.Nlog" />
</extensions>
<!-- 变量 -->
<!-- 控制器、方法,以及是否显示 -->
<variable name="vController"
value="${when:when= '${aspnet-mvc-controller}'=='':then='':else=【url\:${vUrl}】}"></variable>
<!-- Url以及是否显示 -->
<variable name="vUrl"
value="${when:when= '${aspnet-mvc-controller}'=='':then='':else=${aspnet-mvc-controller}/${aspnet-mvc-action}}"></variable>
<!-- 命名空间名称 -->
<variable name="namespace"
value="${when:when='${callsite}'=='':then='':else=${callsite-namespace}}"></variable>
<!-- 类名 -->
<variable name="class-name"
value="${callsite:className=true:methodName=false:includeNamespace=false}"></variable>
<!-- 方法名 -->
<variable name="method-name"
value="${callsite:className=false:methodName=true:includeNamespace=false}"></variable>
<!-- 日期时间格式化 -->
<variable name="date-format"
value="【${date:format=yyyy-MM-dd HH\:mm\:ss}】"></variable>
<!-- 调用类名和方法 || '${class-name}'=='PersonalService' -->
<variable name="caller"
value="${when:when='${class-name}'=='MyResultFilter':inner=【${vUrl}】:else=【${class-name} - ${method-name} - ${callsite-linenumber}】}"></variable>
<!-- 写入日志的目标配置 -->
<targets>
<!-- 信息 -->
<target xsi:type="File"
name="info"
fileName="logs/info/${shortdate}.txt"
readOnly="true"
layout="【${time}】【${uppercase:${level}}】${caller}${vController}${message}" />
<!-- 错误 -->
<target xsi:type="File"
name="error"
fileName="logs/error/${shortdate}.txt"
readOnly="true"
layout="【${time}】【${uppercase:${level}}】${caller}${vController}${message}" />
<!-- 调试 -->
<target xsi:type="File"
name="debug"
fileName="logs/debug/${shortdate}.txt"
readOnly="true"
layout="【${time}】【${uppercase:${level}}】${caller}${vController}${message}" />
<!-- 控制台输出 -->
<target xsi:type="Console"
name="console"
layout="${date-format}${uppercase:${level}}${caller}${vController}${message}" />
</targets>
<!-- 映射规则 -->
<rules>
<!-- 调试 -->
<logger name="*" minlevel="Trace" maxlevel="Debug" writeTo="debug" />
<!-- 警告 -->
<logger name="*" level="Info" writeTo="info" />
<!-- 错误 -->
<logger name="*" minlevel="Warn" maxlevel="Error" writeTo="error" />
<!-- 控制台输出 -->
<logger name="*" minlevel="Info" maxlevel="Error" writeTo="console" final="true" />
</rules>
</nlog>
Loading…
Cancel
Save