江苏工伤联网结算接口对接实现逻辑设计.md 56 KB

江苏工伤联网结算接口对接实现逻辑设计

版本信息

版本号 修改内容 修改日期 修改人
V1.0 初始版本设计 2024.12.19 系统

目录


1 设计概述

1.1 设计目标

基于江苏省工伤机构联网结算接口开发手册(V2.1版本),设计一个统一的工伤联网接口对接业务类,实现与江苏省工伤联网系统的无缝对接。

1.2 设计原则

  1. 统一封装:参考 JiangSuSocialCardBusiness.cs 的成功模式,提供统一的业务接口
  2. 简化调用:通过参数区分不同业务接口,HIS系统调用更简洁
  3. 完全合规:严格按照工伤文档规范实现,确保接口合规性
  4. 易于集成:可直接嵌套到现有HIS系统中使用
  5. 高度复用:一套代码支持所有工伤联网业务场景

1.3 核心思路

采用用户建议的实现方案:

  • 初始化函数:负责系统初始化和环境检查
  • 通用接口函数:统一的业务处理入口,通过参数区分不同交易
  • 参数化设计:所有具体接口通过传入参数动态调用
  • 直接嵌套:可直接集成到HIS系统业务流程中

2 架构设计

2.1 系统架构图

┌─────────────────────────────────────────┐
│           HIS医院信息系统                │
├─────────────────────────────────────────┤
│        JiangSuWorkInjuryBusiness        │
│    ┌─────────────┬─────────────────────┐ │
│    │ 初始化函数   │   通用接口函数       │ │
│    │ Initialize  │   ProcessTransaction │ │
│    └─────────────┴─────────────────────┘ │
├─────────────────────────────────────────┤
│          JSSiInterface.dll               │
│   ┌─────────────┬─────────────────────┐  │
│   │ Si_INIT     │     Si_Busi         │  │
│   └─────────────┴─────────────────────┘  │
├─────────────────────────────────────────┤
│         HTTPS/SSL安全传输协议            │
├─────────────────────────────────────────┤
│        江苏省工伤联网中心系统            │
└─────────────────────────────────────────┘

2.2 接口分类体系

根据工伤文档,接口共分为4大类:

分类 交易编号范围 主要功能 实现策略
对账类 1320-1321 总额对账、明细对账 统一对账处理
认证类 9001-9002 签到、签退 会话管理
业务类 1101, 22XX, 81XX, 23XX 读卡、登记、结算、体检、转院 核心业务处理
下载类 1301, 91XX 数据下载、查询 数据同步

3 核心类设计

3.1 主业务类:JiangSuWorkInjuryBusiness

/// <summary>
/// 江苏工伤联网结算业务类
/// 基于JSSiInterface.dll动态库,严格按照江苏工伤联网接口规范v2.1实现
/// 参考JiangSuSocialCardBusiness.cs的成功架构模式
/// </summary>
public class JiangSuWorkInjuryBusiness
{
    #region DLL导入声明 - 严格按照工伤文档规范
    
    /// <summary>
    /// 初始化函数 - 检查整个运行环境
    /// </summary>
    /// <param name="pErrMsg">错误信息</param>
    /// <returns>成功:0,失败:-1</returns>
    [DllImport("JSSiInterface.dll", EntryPoint = "Si_INIT", CharSet = CharSet.Ansi)]
    private extern static int Si_INIT(StringBuilder pErrMsg);
    
    /// <summary>
    /// 交易函数 - 处理所有业务交易
    /// </summary>
    /// <param name="inputdata">输入参数JSON字符串</param>
    /// <param name="outputdata">输出参数JSON字符串</param>
    /// <returns>成功:0,失败:<0</returns>
    [DllImport("JSSiInterface.dll", EntryPoint = "Si_Busi", CharSet = CharSet.Ansi)]
    private extern static int Si_Busi(string inputdata, StringBuilder outputdata);
    
    #endregion
    
    #region 状态管理和内部变量
    
    /// <summary>
    /// 系统初始化状态
    /// </summary>
    private static bool isInitialized = false;
    
    /// <summary>
    /// 当前配置信息
    /// </summary>
    private static WorkInjuryConfig currentConfig = null;
    
    /// <summary>
    /// 当前签到流水号
    /// </summary>
    private static string currentSignNo = "";
    
    /// <summary>
    /// 签到时间
    /// </summary>
    private static DateTime signInTime = DateTime.MinValue;
    
    /// <summary>
    /// 签到操作员
    /// </summary>
    private static string signInOperator = "";
    
    /// <summary>
    /// 报文ID缓存(用于冲正交易)
    /// </summary>
    private static readonly Dictionary<string, TransactionRecord> transactionRecords = new Dictionary<string, TransactionRecord>();
    
    /// <summary>
    /// 序列号计数器(用于生成唯一报文ID)
    /// </summary>
    private static int sequenceCounter = 0;
    private static readonly object sequenceLock = new object();
    
    /// <summary>
    /// 交易记录类
    /// </summary>
    private class TransactionRecord
    {
        public string MessageId { get; set; }
        public string TransactionCode { get; set; }
        public DateTime TransactionTime { get; set; }
        public string OperatorId { get; set; }
    }
    
    #endregion
}

3.2 配置管理类

/// <summary>
/// 江苏工伤联网配置类 - 严格按照工伤文档规范定义
/// </summary>
public class WorkInjuryConfig
{
    /// <summary>
    /// 协议机构编号 - 由江苏人社分配
    /// </summary>
    public string FixmedinsCode { get; set; } = "H00001";
    
    /// <summary>
    /// 协议机构名称
    /// </summary>
    public string FixmedinsName { get; set; } = "第一人民医院";
    
    /// <summary>
    /// 接收方系统代码 - 默认"JSYTH"
    /// </summary>
    public string ReceiverSysCode { get; set; } = "JSYTH";
    
    /// <summary>
    /// 接口版本号 - 如"V2.1"
    /// </summary>
    public string InterfaceVersion { get; set; } = "V2.1";
    
    /// <summary>
    /// 经办人类别 - 1:经办人 2:自助终端 3:移动终端
    /// </summary>
    public string OperatorType { get; set; } = "1";
    
    /// <summary>
    /// 默认经办人编号
    /// </summary>
    public string DefaultOperator { get; set; } = "001";
    
    /// <summary>
    /// 默认经办人姓名
    /// </summary>
    public string DefaultOperatorName { get; set; } = "系统管理员";
}

3.3 交易请求参数类

/// <summary>
/// 工伤联网交易请求参数 - 按照工伤文档标准格式
/// </summary>
public class WorkInjuryTransactionRequest
{
    /// <summary>
    /// 交易编号 - 4位数字
    /// </summary>
    public string TransactionCode { get; set; }
    
    /// <summary>
    /// 业务参数 - 具体交易的输入参数
    /// </summary>
    public object BusinessParams { get; set; }
    
    /// <summary>
    /// 识别方式 - 1:实体社保卡 2:电子凭证
    /// </summary>
    public string IdentifyMode { get; set; } = "1";
    
    /// <summary>
    /// 电子社保卡二维码(识别方式为2时必填)
    /// </summary>
    public string QrCodeInfo { get; set; } = "";
    
    /// <summary>
    /// 经办人编号(可选,使用默认值)
    /// </summary>
    public string OperatorId { get; set; } = "";
    
    /// <summary>
    /// 经办人姓名(可选,使用默认值)
    /// </summary>
    public string OperatorName { get; set; } = "";
}

4 接口实现策略

4.1 统一处理流程

public static JObject ProcessTransaction(WorkInjuryTransactionRequest request)
{
    var result = new JObject();
    
    try
    {
        // 1. 检查初始化状态
        if (!isInitialized)
        {
            var initResult = Initialize();
            if (!(bool)initResult["success"])
            {
                return initResult;
            }
        }
        
        // 2. 构造标准输入参数
        var inputJson = BuildStandardInput(request);
        
        // 3. 调用底层DLL
        StringBuilder outputBuffer = new StringBuilder(40000);
        int dllResult = Si_Busi(inputJson, outputBuffer);
        
        // 4. 解析输出结果
        result = ParseStandardOutput(outputBuffer.ToString(), dllResult);
        
        // 5. 特殊业务处理
        result = ProcessSpecialBusiness(request.TransactionCode, result);
        
    }
    catch (Exception ex)
    {
        result = BuildErrorResult(ex);
    }
    
    return result;
}

4.2 参数化交易映射

/// <summary>
/// 交易代码映射表 - 基于工伤文档接口列表
/// </summary>
private static readonly Dictionary<string, string> TransactionMapping = new Dictionary<string, string>
{
    // 认证类
    {"SignIn", "9001"},           // 签到
    {"SignOut", "9002"},          // 签退
    
    // 业务类 - 核心功能
    {"ReadCard", "1101"},         // 读卡
    {"RegisterPatient", "2201"},  // 门诊/住院登记
    {"CancelRegister", "2202"},   // 登记撤销
    {"ModifyRegister", "2203"},   // 登记信息修改
    {"UploadPrescription", "2204"}, // 处方明细上报
    {"CancelPrescription", "2205"}, // 处方明细撤销
    {"PreSettle", "2206"},        // 费用预结算
    {"Settle", "2207"},           // 费用结算
    {"CancelSettle", "2208"},     // 费用结算撤销
    {"ReverseTransaction", "2209"}, // 冲正交易
    
    // 体检类 - 体检协议机构使用
    {"QueryExamSchedule", "8101"}, // 查询体检排班信息
    {"UpdateExamSchedule", "8102"}, // 更新体检排班信息
    {"QueryExamReservation", "8103"}, // 查询体检预约信息
    {"ExamRegister", "8104"},     // 体检登记
    {"UploadExamDetail", "8105"}, // 上传体检明细
    {"QueryExamSettle", "8106"},  // 查询体检结算信息
    {"QueryExamDetail", "8107"},  // 查询体检明细
    {"ConfirmExamResult", "8108"}, // 体检结果确认
    {"QuerySupplementCard", "8109"}, // 补刷卡登记查询
    
    // 转院类
    {"UploadReferral", "2301"},   // 转诊转院申请信息上传
    {"QueryReferral", "2302"},    // 转诊转院申请信息查询
    {"CancelReferral", "2303"},   // 转诊转院申请信息撤销
    
    // 对账类
    {"TotalAccount", "1320"},     // 总额对账
    {"DetailAccount", "1321"},    // 明细对账
    
    // 下载类
    {"BatchDownload", "1301"},    // 批量数据下载
    {"QueryFeeDetail", "9103"},   // 费用明细详细信息下载
    {"QueryPrescriptionDetail", "9104"}, // 处方明细下载
    {"QueryRecentVisit", "9105"}  // 参保人近期就诊信息查询
};

5 具体实现方案

5.1 初始化函数实现

/// <summary>
/// 初始化江苏工伤联网系统
/// 参考JiangSuSocialCardBusiness的Initialize方法,但适配工伤业务
/// </summary>
/// <param name="config">配置参数</param>
/// <returns>初始化结果</returns>
public static JObject Initialize(WorkInjuryConfig config = null)
{
    var result = new JObject();
    
    try
    {
        // 使用默认配置或传入配置
        if (config == null)
        {
            config = new WorkInjuryConfig();
        }
        
        // 检查DLL文件存在性
        var dllCheckResult = CheckDllExists();
        if (!(bool)dllCheckResult["success"])
        {
            return dllCheckResult;
        }
        
        // 调用底层初始化函数
        StringBuilder errMsg = new StringBuilder(1024);
        int initResult = Si_INIT(errMsg);
        
        if (initResult == 0)
        {
            isInitialized = true;
            currentConfig = config;
            
            result["success"] = true;
            result["code"] = 200;
            result["message"] = "江苏工伤联网系统初始化成功";
            result["device"] = "江苏工伤联网接口";
            result["timestamp"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            result["version"] = config.InterfaceVersion;
            result["dllErrorMsg"] = errMsg.ToString();
        }
        else
        {
            string errorMsg = errMsg.ToString();
            result["success"] = false;
            result["code"] = 1000 + Math.Abs(initResult);
            result["message"] = $"江苏工伤联网系统初始化失败: {errorMsg}";
            result["device"] = "江苏工伤联网接口";
            result["errorCode"] = initResult;
            result["dllErrorMsg"] = errorMsg;
        }
    }
    catch (Exception ex)
    {
        result["success"] = false;
        result["code"] = 1001;
        result["message"] = $"江苏工伤联网系统初始化异常: {ex.Message}";
        result["device"] = "江苏工伤联网接口";
        result["exception"] = ex.GetType().Name;
    }
    
    return result;
}

5.2 通用接口函数实现

/// <summary>
/// 通用工伤联网交易处理接口
/// 支持所有工伤文档定义的交易类型
/// </summary>
/// <param name="transactionName">交易名称(可使用中文名称或交易编号)</param>
/// <param name="businessParams">业务参数对象</param>
/// <param name="identifyMode">识别方式:1-实体社保卡,2-电子凭证</param>
/// <param name="qrCodeInfo">电子社保卡二维码(识别方式为2时必填)</param>
/// <param name="operatorId">经办人编号(可选)</param>
/// <param name="operatorName">经办人姓名(可选)</param>
/// <returns>交易处理结果</returns>
public static JObject ProcessWorkInjuryTransaction(
    string transactionName,
    object businessParams = null,
    string identifyMode = "1",
    string qrCodeInfo = "",
    string operatorId = "",
    string operatorName = "")
{
    var result = new JObject();
    
    try
    {
        // 1. 解析交易编号
        string transactionCode = GetTransactionCode(transactionName);
        if (string.IsNullOrEmpty(transactionCode))
        {
            result["success"] = false;
            result["code"] = 1002;
            result["message"] = $"不支持的交易类型: {transactionName}";
            result["device"] = "江苏工伤联网接口";
            return result;
        }
        
        // 2. 检查初始化状态
        if (!isInitialized)
        {
            var autoInitResult = Initialize();
            if (!(bool)autoInitResult["success"])
            {
                result["success"] = false;
                result["code"] = 1003;
                result["message"] = "江苏工伤联网系统未初始化";
                result["device"] = "江苏工伤联网接口";
                result["autoInitError"] = autoInitResult["message"];
                return result;
            }
        }
        
        // 3. 检查签到状态(除签到交易外)
        if (transactionCode != "9001" && string.IsNullOrEmpty(currentSignNo))
        {
            var signInResult = ProcessWorkInjuryTransaction("SignIn");
            if (!(bool)signInResult["success"])
            {
                result["success"] = false;
                result["code"] = 1004;
                result["message"] = "自动签到失败,无法进行业务交易";
                result["device"] = "江苏工伤联网接口";
                result["signInError"] = signInResult["message"];
                return result;
            }
        }
        
        // 4. 构造标准输入参数
        var inputData = BuildTransactionInput(transactionCode, businessParams, identifyMode, qrCodeInfo, operatorId, operatorName);
        string inputJson = JsonConvert.SerializeObject(inputData, Formatting.None);
        
        // 5. 调用底层DLL交易函数
        StringBuilder outputBuffer = new StringBuilder(40000);
        int dllResult = Si_Busi(inputJson, outputBuffer);
        
        // 6. 解析和处理返回结果
        string outputJson = outputBuffer.ToString();
        result = ParseTransactionOutput(outputJson, dllResult, transactionCode);
        
        // 7. 特殊交易后处理
        PostProcessTransaction(transactionCode, result);
        
    }
    catch (Exception ex)
    {
        result["success"] = false;
        result["code"] = 1005;
        result["message"] = $"工伤联网交易异常: {ex.Message}";
        result["device"] = "江苏工伤联网接口";
        result["exception"] = ex.GetType().Name;
        result["transactionName"] = transactionName;
    }
    
    return result;
}

/// <summary>
/// 特殊交易后处理逻辑
/// </summary>
private static void PostProcessTransaction(string transactionCode, JObject result)
{
    if ((bool)result["success"])
    {
        switch (transactionCode)
        {
            case "9001": // 签到交易成功
                var signData = result["data"];
                if (signData != null)
                {
                    currentSignNo = signData["sign_no"]?.ToString() ?? "";
                    signInTime = DateTime.Now;
                    signInOperator = currentConfig?.DefaultOperator ?? "";
                    
                    // 记录签到成功日志
                    LogInfo($"签到成功,流水号: {currentSignNo}, 时间: {signInTime:yyyy-MM-dd HH:mm:ss}");
                }
                break;
                
            case "9002": // 签退交易成功
                // 清除签到状态
                currentSignNo = "";
                signInTime = DateTime.MinValue;
                signInOperator = "";
                
                LogInfo($"签退成功,时间: {DateTime.Now:yyyy-MM-dd HH:mm:ss}");
                break;
        }
    }
}

5.3 标准输入参数构造

/// <summary>
/// 构造标准的工伤联网交易输入参数
/// 严格按照工伤文档表2格式构造,支持特殊交易格式
/// </summary>
private static object BuildTransactionInput(string transactionCode, object businessParams, 
    string identifyMode, string qrCodeInfo, string operatorId, string operatorName)
{
    // 生成唯一的发送方报文ID:协议机构编号(6)+时间(14)+顺序号(4)
    string msgId = GenerateMessageId();
    
    // 使用配置的经办人信息或传入的参数
    string finalOperatorId = string.IsNullOrEmpty(operatorId) ? currentConfig.DefaultOperator : operatorId;
    string finalOperatorName = string.IsNullOrEmpty(operatorName) ? currentConfig.DefaultOperatorName : operatorName;
    
    // 构造基础参数对象
    var baseInputData = new
    {
        infno = transactionCode,                          // 交易编号
        msgid = msgId,                                    // 发送方报文ID
        recer_sys_code = currentConfig.ReceiverSysCode,   // 接收方系统代码
        infver = currentConfig.InterfaceVersion,          // 接口版本号
        opter_type = currentConfig.OperatorType,          // 经办人类别
        opter = finalOperatorId,                          // 经办人
        opter_name = finalOperatorName,                   // 经办人姓名
        inf_time = DateTime.Now.ToString("yyyyMMddHHmmss"), // 交易时间
        fixmedins_code = currentConfig.FixmedinsCode,     // 协议机构编号
        fixmedins_name = currentConfig.FixmedinsName,     // 协议机构名称
        sign_no = transactionCode == "9001" ? "" : currentSignNo, // 签到流水号
        idfi_mode = identifyMode,                         // 识别方式
        qrcode_info = qrCodeInfo                          // 电子社保卡二维码
    };
    
    // 处理特殊交易格式
    object finalInputData = BuildSpecialTransactionInput(baseInputData, transactionCode, businessParams);
    
    // 保存发送方报文ID用于可能的冲正操作
    SaveMessageId(msgId, transactionCode);
    
    return finalInputData;
}

/// <summary>
/// 处理特殊交易的输入格式
/// 按照工伤文档要求,某些交易需要特殊的参数格式
/// </summary>
private static object BuildSpecialTransactionInput(object baseInputData, string transactionCode, object businessParams)
{
    switch (transactionCode)
    {
        case "2204": // 处方明细上报 - 使用feedetail代替input
            return new
            {
                // 复制基础参数
                infno = ((dynamic)baseInputData).infno,
                msgid = ((dynamic)baseInputData).msgid,
                recer_sys_code = ((dynamic)baseInputData).recer_sys_code,
                infver = ((dynamic)baseInputData).infver,
                opter_type = ((dynamic)baseInputData).opter_type,
                opter = ((dynamic)baseInputData).opter,
                opter_name = ((dynamic)baseInputData).opter_name,
                inf_time = ((dynamic)baseInputData).inf_time,
                fixmedins_code = ((dynamic)baseInputData).fixmedins_code,
                fixmedins_name = ((dynamic)baseInputData).fixmedins_name,
                sign_no = ((dynamic)baseInputData).sign_no,
                idfi_mode = ((dynamic)baseInputData).idfi_mode,
                qrcode_info = ((dynamic)baseInputData).qrcode_info,
                // 特殊格式:使用feedetail替代input
                feedetail = businessParams ?? new object[] { }
            };
            
        case "8105": // 上传体检明细 - 使用tjfeedetail代替input
            return new
            {
                // 复制基础参数
                infno = ((dynamic)baseInputData).infno,
                msgid = ((dynamic)baseInputData).msgid,
                recer_sys_code = ((dynamic)baseInputData).recer_sys_code,
                infver = ((dynamic)baseInputData).infver,
                opter_type = ((dynamic)baseInputData).opter_type,
                opter = ((dynamic)baseInputData).opter,
                opter_name = ((dynamic)baseInputData).opter_name,
                inf_time = ((dynamic)baseInputData).inf_time,
                fixmedins_code = ((dynamic)baseInputData).fixmedins_code,
                fixmedins_name = ((dynamic)baseInputData).fixmedins_name,
                sign_no = ((dynamic)baseInputData).sign_no,
                idfi_mode = ((dynamic)baseInputData).idfi_mode,
                qrcode_info = ((dynamic)baseInputData).qrcode_info,
                // 特殊格式:使用tjfeedetail替代input
                tjfeedetail = businessParams ?? new object[] { }
            };
            
        default: // 标准交易格式
            return new
            {
                // 复制基础参数
                infno = ((dynamic)baseInputData).infno,
                msgid = ((dynamic)baseInputData).msgid,
                recer_sys_code = ((dynamic)baseInputData).recer_sys_code,
                infver = ((dynamic)baseInputData).infver,
                opter_type = ((dynamic)baseInputData).opter_type,
                opter = ((dynamic)baseInputData).opter,
                opter_name = ((dynamic)baseInputData).opter_name,
                inf_time = ((dynamic)baseInputData).inf_time,
                fixmedins_code = ((dynamic)baseInputData).fixmedins_code,
                fixmedins_name = ((dynamic)baseInputData).fixmedins_name,
                sign_no = ((dynamic)baseInputData).sign_no,
                idfi_mode = ((dynamic)baseInputData).idfi_mode,
                qrcode_info = ((dynamic)baseInputData).qrcode_info,
                // 标准格式:使用input
                input = businessParams ?? new { }
            };
    }
}

5.4 便捷方法封装

// 为常用交易提供便捷方法,简化调用

/// <summary>
/// 读卡交易 - 获取工伤人员基本信息
/// </summary>
public static JObject ReadWorkInjuryCard(string identifyMode = "1", string qrCodeInfo = "")
{
    return ProcessWorkInjuryTransaction("ReadCard", null, identifyMode, qrCodeInfo);
}

/// <summary>
/// 门诊/住院登记
/// </summary>
public static JObject RegisterPatient(object registerParams, string identifyMode = "1")
{
    return ProcessWorkInjuryTransaction("RegisterPatient", registerParams, identifyMode);
}

/// <summary>
/// 费用预结算
/// </summary>
public static JObject PreSettlement(object settlementParams)
{
    return ProcessWorkInjuryTransaction("PreSettle", settlementParams);
}

/// <summary>
/// 费用结算
/// </summary>
public static JObject Settlement(object settlementParams)
{
    return ProcessWorkInjuryTransaction("Settle", settlementParams);
}

/// <summary>
/// 处方明细上传
/// </summary>
public static JObject UploadPrescription(object prescriptionDetails)
{
    return ProcessWorkInjuryTransaction("UploadPrescription", prescriptionDetails);
}

/// <summary>
/// 签到交易
/// </summary>
public static JObject SignIn()
{
    return ProcessWorkInjuryTransaction("SignIn");
}

/// <summary>
/// 签退交易
/// </summary>
public static JObject SignOut()
{
    return ProcessWorkInjuryTransaction("SignOut");
}

/// <summary>
/// 冲正交易
/// </summary>
public static JObject ReverseTransaction(string originalTransactionCode, string originalMessageId)
{
    var reverseParams = new
    {
        infno = originalTransactionCode,
        msgid = originalMessageId
    };
    return ProcessWorkInjuryTransaction("ReverseTransaction", reverseParams);
}

/// <summary>
/// 根据交易记录进行冲正(便捷方法)
/// </summary>
public static JObject ReverseTransactionByRecord(string messageId)
{
    if (transactionRecords.ContainsKey(messageId))
    {
        var record = transactionRecords[messageId];
        return ReverseTransaction(record.TransactionCode, record.MessageId);
    }
    else
    {
        return new JObject
        {
            ["success"] = false,
            ["code"] = 1006,
            ["message"] = $"未找到报文ID对应的交易记录: {messageId}",
            ["device"] = "江苏工伤联网接口"
        };
    }
}

/// <summary>
/// 获取当前签到状态
/// </summary>
public static JObject GetSignInStatus()
{
    return new JObject
    {
        ["success"] = true,
        ["code"] = 200,
        ["message"] = "签到状态查询成功",
        ["data"] = new JObject
        {
            ["isSignedIn"] = !string.IsNullOrEmpty(currentSignNo),
            ["signNo"] = currentSignNo,
            ["signInTime"] = signInTime == DateTime.MinValue ? "" : signInTime.ToString("yyyy-MM-dd HH:mm:ss"),
            ["signInOperator"] = signInOperator,
            ["isInitialized"] = isInitialized
        }
    };
}

/// <summary>
/// 批量处方明细上传 - 便捷方法
/// </summary>
public static JObject BatchUploadPrescriptions(List<object> prescriptionList, int batchSize = 50)
{
    var result = new JObject();
    var successResults = new JArray();
    var failedResults = new JArray();
    
    try
    {
        if (prescriptionList == null || prescriptionList.Count == 0)
        {
            result["success"] = false;
            result["code"] = 1007;
            result["message"] = "处方明细列表为空";
            return result;
        }
        
        // 按批次处理(单次最多50条)
        for (int i = 0; i < prescriptionList.Count; i += batchSize)
        {
            var batch = prescriptionList.Skip(i).Take(batchSize).ToList();
            var batchResult = UploadPrescription(batch);
            
            if ((bool)batchResult["success"])
            {
                successResults.Add(new JObject
                {
                    ["batchIndex"] = i / batchSize + 1,
                    ["count"] = batch.Count,
                    ["result"] = batchResult
                });
            }
            else
            {
                failedResults.Add(new JObject
                {
                    ["batchIndex"] = i / batchSize + 1,
                    ["count"] = batch.Count,
                    ["result"] = batchResult
                });
            }
        }
        
        result["success"] = failedResults.Count == 0;
        result["code"] = result["success"] ? 200 : 1008;
        result["message"] = $"批量上传完成,成功{successResults.Count}批,失败{failedResults.Count}批";
        result["data"] = new JObject
        {
            ["totalBatches"] = (prescriptionList.Count + batchSize - 1) / batchSize,
            ["successBatches"] = successResults.Count,
            ["failedBatches"] = failedResults.Count,
            ["successResults"] = successResults,
            ["failedResults"] = failedResults
        };
    }
    catch (Exception ex)
    {
        result["success"] = false;
        result["code"] = 1009;
        result["message"] = $"批量上传异常: {ex.Message}";
        result["exception"] = ex.GetType().Name;
    }
    
    return result;
}

/// <summary>
/// 完整的工伤患者就诊流程 - 一站式便捷方法
/// </summary>
public static JObject CompleteWorkInjuryProcess(object patientRegisterParams, List<object> prescriptionList, object settlementParams)
{
    var result = new JObject();
    var processSteps = new JArray();
    
    try
    {
        // 步骤1:读卡
        var readCardResult = ReadWorkInjuryCard();
        processSteps.Add(new JObject { ["step"] = "读卡", ["result"] = readCardResult });
        
        if (!(bool)readCardResult["success"])
        {
            result["success"] = false;
            result["message"] = "读卡失败,流程终止";
            result["processSteps"] = processSteps;
            return result;
        }
        
        // 步骤2:患者登记
        var registerResult = RegisterPatient(patientRegisterParams);
        processSteps.Add(new JObject { ["step"] = "患者登记", ["result"] = registerResult });
        
        if (!(bool)registerResult["success"])
        {
            result["success"] = false;
            result["message"] = "患者登记失败,流程终止";
            result["processSteps"] = processSteps;
            return result;
        }
        
        // 步骤3:上传处方明细
        var uploadResult = BatchUploadPrescriptions(prescriptionList);
        processSteps.Add(new JObject { ["step"] = "上传处方", ["result"] = uploadResult });
        
        if (!(bool)uploadResult["success"])
        {
            result["success"] = false;
            result["message"] = "处方上传失败,流程终止";
            result["processSteps"] = processSteps;
            return result;
        }
        
        // 步骤4:费用预结算
        var preSettleResult = PreSettlement(settlementParams);
        processSteps.Add(new JObject { ["step"] = "费用预结算", ["result"] = preSettleResult });
        
        if (!(bool)preSettleResult["success"])
        {
            result["success"] = false;
            result["message"] = "费用预结算失败,流程终止";
            result["processSteps"] = processSteps;
            return result;
        }
        
        // 步骤5:正式结算
        var settleResult = Settlement(settlementParams);
        processSteps.Add(new JObject { ["step"] = "正式结算", ["result"] = settleResult });
        
        result["success"] = (bool)settleResult["success"];
        result["code"] = result["success"] ? 200 : 1010;
        result["message"] = result["success"] ? "工伤就诊流程全部完成" : "正式结算失败";
        result["processSteps"] = processSteps;
        result["finalSettlementData"] = settleResult["data"];
    }
    catch (Exception ex)
    {
        result["success"] = false;
        result["code"] = 1011;
        result["message"] = $"工伤就诊流程异常: {ex.Message}";
        result["processSteps"] = processSteps;
        result["exception"] = ex.GetType().Name;
    }
    
    return result;
}

/// <summary>
/// 智能重试交易 - 带指数退避算法
/// </summary>
public static JObject SmartRetryTransaction(string transactionName, object businessParams, 
    int maxRetries = 3, int baseDelayMs = 1000, double backoffMultiplier = 2.0)
{
    JObject lastResult = null;
    
    for (int attempt = 0; attempt < maxRetries; attempt++)
    {
        try
        {
            lastResult = ProcessWorkInjuryTransaction(transactionName, businessParams);
            
            // 成功则立即返回
            if ((bool)lastResult["success"])
            {
                lastResult["retryInfo"] = new JObject
                {
                    ["attemptCount"] = attempt + 1,
                    ["maxRetries"] = maxRetries,
                    ["finalAttempt"] = true
                };
                return lastResult;
            }
            
            // 判断是否值得重试
            int errorCode = (int)lastResult["code"];
            if (!IsRetryableError(errorCode))
            {
                lastResult["retryInfo"] = new JObject
                {
                    ["attemptCount"] = attempt + 1,
                    ["maxRetries"] = maxRetries,
                    ["retryable"] = false,
                    ["reason"] = "错误类型不可重试"
                };
                break;
            }
            
            // 如果不是最后一次尝试,则等待后重试
            if (attempt < maxRetries - 1)
            {
                int delayMs = (int)(baseDelayMs * Math.Pow(backoffMultiplier, attempt));
                Thread.Sleep(delayMs);
                
                LogInfo($"交易 {transactionName} 第 {attempt + 1} 次尝试失败,{delayMs}ms后重试");
            }
        }
        catch (Exception ex)
        {
            lastResult = new JObject
            {
                ["success"] = false,
                ["code"] = 1012,
                ["message"] = $"智能重试异常: {ex.Message}",
                ["exception"] = ex.GetType().Name,
                ["retryInfo"] = new JObject
                {
                    ["attemptCount"] = attempt + 1,
                    ["maxRetries"] = maxRetries,
                    ["exceptionAttempt"] = true
                }
            };
        }
    }
    
    // 所有重试都失败了
    if (lastResult != null)
    {
        lastResult["retryInfo"] = new JObject
        {
            ["attemptCount"] = maxRetries,
            ["maxRetries"] = maxRetries,
            ["allAttemptsFailed"] = true
        };
    }
    
    return lastResult ?? new JObject 
    { 
        ["success"] = false, 
        ["message"] = "智能重试完全失败" 
    };
}

/// <summary>
/// 交易统计和监控 - 获取交易统计信息
/// </summary>
public static JObject GetTransactionStatistics()
{
    try
    {
        var stats = new JObject
        {
            ["totalTransactions"] = transactionRecords.Count,
            ["oldestTransaction"] = transactionRecords.Values.Any() 
                ? transactionRecords.Values.Min(r => r.TransactionTime).ToString("yyyy-MM-dd HH:mm:ss")
                : "",
            ["newestTransaction"] = transactionRecords.Values.Any()
                ? transactionRecords.Values.Max(r => r.TransactionTime).ToString("yyyy-MM-dd HH:mm:ss")
                : "",
            ["transactionsByType"] = new JObject()
        };
        
        // 按交易类型统计
        var groupedTransactions = transactionRecords.Values
            .GroupBy(r => r.TransactionCode)
            .ToDictionary(g => g.Key, g => g.Count());
            
        foreach (var kvp in groupedTransactions)
        {
            ((JObject)stats["transactionsByType"])[kvp.Key] = kvp.Value;
        }
        
        return new JObject
        {
            ["success"] = true,
            ["code"] = 200,
            ["message"] = "交易统计获取成功",
            ["data"] = stats,
            ["timestamp"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
        };
    }
    catch (Exception ex)
    {
        return new JObject
        {
            ["success"] = false,
            ["code"] = 1013,
            ["message"] = $"获取交易统计异常: {ex.Message}",
            ["exception"] = ex.GetType().Name
        };
    }
}

/// <summary>
/// 系统健康检查 - 全面的系统状态检查
/// </summary>
public static JObject HealthCheck()
{
    var healthResult = new JObject();
    var checks = new JObject();
    bool overallHealthy = true;
    
    try
    {
        // 1. DLL文件检查
        var dllCheck = CheckDllExists();
        checks["dllFile"] = dllCheck;
        if (!(bool)dllCheck["success"]) overallHealthy = false;
        
        // 2. 初始化状态检查
        checks["initialization"] = new JObject
        {
            ["status"] = isInitialized ? "initialized" : "not_initialized",
            ["healthy"] = isInitialized
        };
        if (!isInitialized) overallHealthy = false;
        
        // 3. 签到状态检查
        var signInStatus = GetSignInStatus();
        checks["signInStatus"] = signInStatus;
        bool isSignedIn = (bool)signInStatus["data"]["isSignedIn"];
        if (!isSignedIn) overallHealthy = false;
        
        // 4. 配置检查
        checks["configuration"] = new JObject
        {
            ["hasConfig"] = currentConfig != null,
            ["fixmedinsCode"] = currentConfig?.FixmedinsCode ?? "",
            ["interfaceVersion"] = currentConfig?.InterfaceVersion ?? ""
        };
        if (currentConfig == null) overallHealthy = false;
        
        // 5. 内存使用检查
        var process = System.Diagnostics.Process.GetCurrentProcess();
        checks["memory"] = new JObject
        {
            ["workingSetMB"] = Math.Round(process.WorkingSet64 / 1024.0 / 1024.0, 2),
            ["privateMemoryMB"] = Math.Round(process.PrivateMemorySize64 / 1024.0 / 1024.0, 2)
        };
        
        // 6. 交易记录检查
        checks["transactionRecords"] = new JObject
        {
            ["count"] = transactionRecords.Count,
            ["healthy"] = transactionRecords.Count < 10000 // 避免内存泄漏
        };
        
        healthResult["success"] = true;
        healthResult["code"] = 200;
        healthResult["message"] = overallHealthy ? "系统健康状态良好" : "系统存在健康问题";
        healthResult["healthy"] = overallHealthy;
        healthResult["checks"] = checks;
        healthResult["timestamp"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
    }
    catch (Exception ex)
    {
        healthResult["success"] = false;
        healthResult["code"] = 1014;
        healthResult["message"] = $"健康检查异常: {ex.Message}";
        healthResult["healthy"] = false;
        healthResult["exception"] = ex.GetType().Name;
    }
    
    return healthResult;
}

#endregion

#region 辅助方法

/// <summary>
/// 生成唯一的发送方报文ID
/// 格式:协议机构编号(6位)+时间(14位)+顺序号(4位)
/// </summary>
private static string GenerateMessageId()
{
    lock (sequenceLock)
    {
        sequenceCounter++;
        if (sequenceCounter > 9999)
        {
            sequenceCounter = 1;
        }
        
        string fixmedinsCode = currentConfig?.FixmedinsCode?.PadLeft(6, '0') ?? "000000";
        string timeStr = DateTime.Now.ToString("yyyyMMddHHmmss");
        string sequenceStr = sequenceCounter.ToString("D4");
        
        return $"{fixmedinsCode}{timeStr}{sequenceStr}";
    }
}

/// <summary>
/// 保存交易记录(用于冲正)
/// </summary>
private static void SaveMessageId(string messageId, string transactionCode)
{
    try
    {
        var record = new TransactionRecord
        {
            MessageId = messageId,
            TransactionCode = transactionCode,
            TransactionTime = DateTime.Now,
            OperatorId = currentConfig?.DefaultOperator ?? ""
        };
        
        transactionRecords[messageId] = record;
        
        // 清理30天前的记录(避免内存泄漏)
        var expireTime = DateTime.Now.AddDays(-30);
        var expiredKeys = transactionRecords.Where(r => r.Value.TransactionTime < expireTime)
                                          .Select(r => r.Key)
                                          .ToList();
        
        foreach (var key in expiredKeys)
        {
            transactionRecords.Remove(key);
        }
    }
    catch (Exception ex)
    {
        LogError($"保存交易记录失败: {ex.Message}");
    }
}

/// <summary>
/// 获取交易编号(支持中文名称和数字编号)
/// </summary>
private static string GetTransactionCode(string transactionName)
{
    if (string.IsNullOrEmpty(transactionName))
        return "";
    
    // 如果已经是4位数字编号,直接返回
    if (transactionName.Length == 4 && transactionName.All(char.IsDigit))
    {
        return transactionName;
    }
    
    // 从映射表中查找
    return TransactionMapping.ContainsKey(transactionName) 
        ? TransactionMapping[transactionName] 
        : "";
}

/// <summary>
/// 检查DLL文件是否存在
/// </summary>
private static JObject CheckDllExists()
{
    var result = new JObject();
    
    try
    {
        string programDir = AppDomain.CurrentDomain.BaseDirectory;
        string dllPath = Path.Combine(programDir, "JSSiInterface.dll");
        
        if (File.Exists(dllPath))
        {
            FileInfo fileInfo = new FileInfo(dllPath);
            
            result["success"] = true;
            result["code"] = 200;
            result["message"] = "JSSiInterface.dll文件检查通过";
            result["data"] = new JObject
            {
                ["dllPath"] = dllPath,
                ["fileSize"] = fileInfo.Length,
                ["lastModified"] = fileInfo.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss")
            };
        }
        else
        {
            result["success"] = false;
            result["code"] = 8001;
            result["message"] = "JSSiInterface.dll文件不存在";
            result["data"] = new JObject
            {
                ["expectedPath"] = dllPath,
                ["suggestion"] = "请将JSSiInterface.dll文件复制到程序目录"
            };
        }
    }
    catch (Exception ex)
    {
        result["success"] = false;
        result["code"] = 8002;
        result["message"] = $"DLL文件检查异常: {ex.Message}";
        result["exception"] = ex.GetType().Name;
    }
    
    return result;
}

/// <summary>
/// 判断是否为可重试的错误
/// </summary>
private static bool IsRetryableError(int errorCode)
{
    // 网络相关错误可重试
    int[] retryableErrors = { 1004, 2000, 2001, 3001, 3002 };
    return retryableErrors.Contains(errorCode);
}

/// <summary>
/// 日志记录 - 信息级别
/// </summary>
private static void LogInfo(string message)
{
    try
    {
        string logDir = "logs/workinjury/";
        if (!Directory.Exists(logDir))
        {
            Directory.CreateDirectory(logDir);
        }
        
        string logFile = Path.Combine(logDir, $"workinjury_{DateTime.Now:yyyyMMdd}.log");
        string logEntry = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} [INFO] {message}{Environment.NewLine}";
        
        File.AppendAllText(logFile, logEntry, Encoding.UTF8);
    }
    catch
    {
        // 日志记录失败不影响主业务
    }
}

/// <summary>
/// 日志记录 - 错误级别
/// </summary>
private static void LogError(string message)
{
    try
    {
        string logDir = "logs/workinjury/";
        if (!Directory.Exists(logDir))
        {
            Directory.CreateDirectory(logDir);
        }
        
        string logFile = Path.Combine(logDir, $"workinjury_{DateTime.Now:yyyyMMdd}.log");
        string logEntry = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} [ERROR] {message}{Environment.NewLine}";
        
        File.AppendAllText(logFile, logEntry, Encoding.UTF8);
    }
    catch
    {
        // 日志记录失败不影响主业务
    }
}

#endregion

}

6 错误处理机制

6.1 多层次错误处理

/// <summary>
/// 解析交易输出结果并进行错误处理
/// </summary>
private static JObject ParseTransactionOutput(string outputJson, int dllResult, string transactionCode)
{
    var result = new JObject();
    
    try
    {
        // DLL层面错误
        if (dllResult != 0)
        {
            result["success"] = false;
            result["code"] = 2000 + Math.Abs(dllResult);
            result["message"] = $"DLL调用失败,错误码: {dllResult}";
            result["device"] = "江苏工伤联网接口";
            result["dllErrorCode"] = dllResult;
            result["transactionCode"] = transactionCode;
            result["rawOutput"] = outputJson;
            return result;
        }
        
        // 解析JSON输出
        if (string.IsNullOrEmpty(outputJson))
        {
            result["success"] = false;
            result["code"] = 2001;
            result["message"] = "交易返回数据为空";
            return result;
        }
        
        var outputData = JObject.Parse(outputJson);
        
        // 业务层面错误检查
        string infcode = outputData["infcode"]?.ToString() ?? "";
        string errMsg = outputData["err_msg"]?.ToString() ?? "";
        string warnMsg = outputData["warn_msg"]?.ToString() ?? "";
        
        if (infcode == "0")
        {
            // 交易成功
            result["success"] = true;
            result["code"] = 200;
            result["message"] = string.IsNullOrEmpty(warnMsg) ? "交易成功" : warnMsg;
            result["data"] = outputData["output"];
            result["transactionCode"] = transactionCode;
            result["infRefMsgId"] = outputData["inf_refmsgid"];
            result["refMsgTime"] = outputData["refmsg_time"];
            result["respondTime"] = outputData["respond_time"];
            result["warnMsg"] = warnMsg;
        }
        else
        {
            // 业务失败
            result["success"] = false;
            result["code"] = 3000 + Math.Abs(int.Parse(infcode));
            result["message"] = string.IsNullOrEmpty(errMsg) ? "交易失败" : errMsg;
            result["transactionCode"] = transactionCode;
            result["businessErrorCode"] = infcode;
            result["businessErrorMsg"] = errMsg;
        }
        
        // 保存完整的原始返回数据
        result["rawOutput"] = outputJson;
        
    }
    catch (JsonException jsonEx)
    {
        result["success"] = false;
        result["code"] = 2002;
        result["message"] = $"返回数据解析失败: {jsonEx.Message}";
        result["rawOutput"] = outputJson;
    }
    catch (Exception ex)
    {
        result["success"] = false;
        result["code"] = 2003;
        result["message"] = $"输出解析异常: {ex.Message}";
        result["exception"] = ex.GetType().Name;
    }
    
    return result;
}

6.2 自动重试机制

/// <summary>
/// 带重试机制的交易处理
/// </summary>
public static JObject ProcessWithRetry(string transactionName, object businessParams, int maxRetries = 3)
{
    for (int i = 0; i < maxRetries; i++)
    {
        var result = ProcessWorkInjuryTransaction(transactionName, businessParams);
        
        // 成功则直接返回
        if ((bool)result["success"])
        {
            return result;
        }
        
        // 判断是否可重试的错误
        int errorCode = (int)result["code"];
        if (IsRetryableError(errorCode) && i < maxRetries - 1)
        {
            // 等待重试
            Thread.Sleep(1000 * (i + 1)); // 递增等待时间
            continue;
        }
        
        // 不可重试或已达最大重试次数
        result["retryCount"] = i + 1;
        return result;
    }
    
    // 理论上不会到达这里
    return new JObject { ["success"] = false, ["message"] = "重试机制异常" };
}

7 集成方案

7.1 HIS系统集成示例

// HIS系统中的调用示例

public class HisWorkInjuryService
{
    /// <summary>
    /// 工伤患者挂号登记业务流程
    /// </summary>
    public async Task<HisResult> WorkInjuryRegisterAsync(HisPatientInfo patientInfo)
    {
        try
        {
            // 1. 读卡获取工伤人员信息
            var readCardResult = JiangSuWorkInjuryBusiness.ReadWorkInjuryCard();
            if (!(bool)readCardResult["success"])
            {
                return HisResult.Fail("读卡失败: " + readCardResult["message"]);
            }
            
            // 2. 构造登记参数
            var registerParams = new
            {
                ipt_otp_no = GenerateUniqueNo(),                    // 门诊流水号
                med_type = patientInfo.MedicalType,                 // 医疗类别
                adm_time = DateTime.Now.ToString("yyyyMMddHHmmss"), // 入院时间
                adm_diag_dscr = patientInfo.DiagnosisCode,         // 诊断疾病编码
                adm_dept_codg = patientInfo.DepartmentCode,        // 科室编码
                atddr_no = patientInfo.DoctorCode,                 // 医生编码
                psn_no = readCardResult["data"]["psn_no"],         // 个人唯一识别码
                qualification_id = ExtractQualificationId(readCardResult) // 工伤医疗费资格审核信息ID
            };
            
            // 3. 执行登记交易
            var registerResult = JiangSuWorkInjuryBusiness.RegisterPatient(registerParams);
            if (!(bool)registerResult["success"])
            {
                return HisResult.Fail("登记失败: " + registerResult["message"]);
            }
            
            // 4. 保存HIS本地数据
            await SaveLocalPatientData(patientInfo, readCardResult, registerResult);
            
            return HisResult.Success("工伤患者登记成功");
        }
        catch (Exception ex)
        {
            return HisResult.Fail($"工伤登记异常: {ex.Message}");
        }
    }
    
    /// <summary>
    /// 工伤费用结算业务流程
    /// </summary>
    public async Task<HisResult> WorkInjurySettleAsync(string visitNo)
    {
        try
        {
            // 1. 验证患者身份
            var readCardResult = JiangSuWorkInjuryBusiness.ReadWorkInjuryCard();
            if (!(bool)readCardResult["success"])
            {
                return HisResult.Fail("患者身份验证失败");
            }
            
            // 2. 上传处方明细
            var prescriptionData = await GetPrescriptionData(visitNo);
            var uploadResult = JiangSuWorkInjuryBusiness.UploadPrescription(prescriptionData);
            if (!(bool)uploadResult["success"])
            {
                return HisResult.Fail("处方上传失败: " + uploadResult["message"]);
            }
            
            // 3. 费用预结算
            var preSettleParams = BuildSettlementParams(visitNo, isPreSettle: true);
            var preSettleResult = JiangSuWorkInjuryBusiness.PreSettlement(preSettleParams);
            if (!(bool)preSettleResult["success"])
            {
                return HisResult.Fail("预结算失败: " + preSettleResult["message"]);
            }
            
            // 4. 正式结算
            var settleParams = BuildSettlementParams(visitNo, isPreSettle: false);
            var settleResult = JiangSuWorkInjuryBusiness.Settlement(settleParams);
            if (!(bool)settleResult["success"])
            {
                return HisResult.Fail("结算失败: " + settleResult["message"]);
            }
            
            // 5. 保存结算结果
            await SaveSettlementResult(visitNo, settleResult);
            
            return HisResult.Success("工伤费用结算成功", settleResult["data"]);
        }
        catch (Exception ex)
        {
            return HisResult.Fail($"工伤结算异常: {ex.Message}");
        }
    }
}

7.2 配置文件示例

<!-- app.config 配置示例 -->
<configuration>
  <appSettings>
    <!-- 江苏工伤联网配置 -->
    <add key="WorkInjury.FixmedinsCode" value="H00001" />
    <add key="WorkInjury.FixmedinsName" value="第一人民医院" />
    <add key="WorkInjury.ReceiverSysCode" value="JSYTH" />
    <add key="WorkInjury.InterfaceVersion" value="V2.1" />
    <add key="WorkInjury.OperatorType" value="1" />
    <add key="WorkInjury.DefaultOperator" value="001" />
    <add key="WorkInjury.DefaultOperatorName" value="系统管理员" />
    
    <!-- 自动重试配置 -->
    <add key="WorkInjury.MaxRetries" value="3" />
    <add key="WorkInjury.RetryInterval" value="1000" />
    
    <!-- 日志配置 -->
    <add key="WorkInjury.LogLevel" value="Info" />
    <add key="WorkInjury.LogPath" value="logs/workinjury/" />
  </appSettings>
</configuration>

8 部署说明

8.1 环境要求

  1. 操作系统:Windows Server 2012 R2 及以上
  2. .NET Framework:4.5 及以上版本
  3. DLL文件:JSSiInterface.dll(由江苏人社提供)
  4. 网络环境:能够访问江苏工伤联网专线网络

8.2 部署步骤

  1. 复制DLL文件

    将 JSSiInterface.dll 复制到应用程序bin目录
    确保DLL文件版本与接口文档版本一致
    
  2. 配置参数设置

    根据医院实际情况修改配置文件中的参数
    协议机构编号和名称需要与江苏人社备案信息一致
    
  3. 权限配置

    确保应用程序有读取DLL文件的权限
    配置网络访问权限
    
  4. 测试验证

    先在测试环境验证接口连通性
    执行签到/签退测试确认基础功能
    进行完整业务流程测试
    

8.3 监控建议

  1. 接口调用监控:记录每次接口调用的结果和耗时
  2. 错误率监控:统计各类交易的成功率和失败原因
  3. 业务量监控:监控日常业务交易量变化
  4. 性能监控:关注响应时间和系统资源使用情况

9 总结

9.1 设计优势

  1. 架构清晰:参考成功的 JiangSuSocialCardBusiness.cs 架构模式
  2. 接口统一:通过参数化设计实现所有交易的统一调用
  3. 完全合规:严格按照江苏工伤联网接口文档规范实现
  4. 易于集成:可直接嵌套到现有HIS系统中使用
  5. 扩展性强:新增交易类型只需要添加映射关系

9.2 关键特性

  • 初始化函数:完整的系统初始化和环境检查
  • 通用接口函数:统一的交易处理入口
  • 参数化调用:通过参数区分不同的业务交易
  • 特殊交易处理:支持处方明细上传等特殊格式交易
  • 签到流水号管理:完善的会话状态管理机制
  • 错误处理机制:多层次的错误处理和智能重试
  • 便捷方法集合:丰富的高级便捷方法
    • 批量处方上传
    • 完整就诊流程
    • 智能重试机制
    • 交易统计监控
    • 系统健康检查
  • 直接嵌套:可无缝集成到HIS系统业务流程
  • 生产级特性:日志记录、内存管理、交易追踪

9.3 实施建议

  1. 分阶段实施:建议按交易类型分阶段实施和测试
  2. 充分测试:在正式上线前进行充分的功能和压力测试
  3. 监控运维:建立完善的监控和运维机制
  4. 文档维护:及时更新技术文档和操作手册

这个设计方案完全符合您的思路,提供了一个初始化函数和一个通用接口函数,通过参数来区分不同的交易类型,可以直接嵌套到HIS系统中使用,大大简化了工伤联网接口的集成复杂度。