一、引言

随着我国成品油零售行业的快速发展,加油站税收监管已成为税务管理的重点领域。传统手工开票模式存在开票效率低、数据易篡改、税源难以监控等问题,导致国家税款流失风险加剧。2026 年国家税务总局发布第 11 号公告,明确要求在成品油零售领域全面推广 "交易即开票" 机制,依托税务乐企平台实现加油交易完成后自动实时开具全数字化电子发票。在此背景下,基于 Java 技术栈开发加油站税控系统,实现加油机数据自动采集、交易实时核验、发票自动开具、数据统一监管,已成为成品油零售行业合规化发展的必然趋势。

Java 技术凭借其跨平台特性、成熟的生态体系、强大的并发处理能力和良好的安全性,在企业级税务系统开发中占据主导地位。本文从需求分析、架构设计、功能实现、代码示例和应用案例五个维度,详细阐述基于 Java 的加油站税控系统开发全过程。

二、系统需求分析

(一)功能需求

加油站税控系统核心功能围绕 "数据采集 - 交易核验 - 税务开票 - 监管存证" 全链路展开。一是加油数据采集,通过 RS-232C 标准接口实时采集加油机报税口数据,包括油品型号、加油量、单价、交易金额、枪号、交易时间等关键信息,数据格式遵循国家税务总局规定的 ASCII 码序列标准。二是税控数据管理,实现月累计加油数据、总累计加油数据的加密存储与防篡改保护,支持税控装置初始化、序列号管理、纳税人识别号绑定。三是电子发票开具,对接税务乐企平台,交易完成后自动匹配油品税收编码,即时生成数电发票并推送至用户端。四是统计报表生成,按日、月、年维度生成销售统计表、税负分析表、发票开具明细表,支持多站点数据汇总。五是系统管理,包括加油站基础信息维护、设备管理、权限控制、操作日志审计等功能。

(二)非功能需求

安全性方面,采用国密算法对交易数据进行加密传输与存储,安全芯片独立承担密钥管理,确保即使主控系统被攻破,核心数据仍受保护。实时性方面,加油数据采集延迟不超过 1 秒,发票开具响应时间不超过 3 秒,支持高并发交易场景。稳定性方面,终端本地配置不少于 8GB 固态存储,支持 WORM 写入模式,可缓存 72 小时以上交易流水,网络中断时业务不中断。可扩展性方面,采用模块化设计,支持不同品牌加油机协议接入,可平滑扩展至连锁加油站集团化管理。

三、系统架构设计

(一)整体架构

系统采用五层分布式架构设计,各层级独立运转、联动协同,形成完整的数据闭环。

终端采集层包含加油机、油卡读卡器、收银终端、支付设备等,负责原始交易数据采集,是数据源头。边缘网关层以数据集线器为核心,承担协议解析、数据清洗、本地加密、签名校验、离线缓存功能,统一各类设备协议输出格式。本地业务层包括加油站零管系统、收银系统、本地缓存服务,负责本地交易结算、断网容错、订单校验。云端服务层为系统核心,涵盖负载均衡、数据加密、交易管理、开票调度、日志审计、设备管控等服务,实现全站点数据汇总与高并发处理。税务对接层基于标准化 API 对接税务乐企平台,完成合规报文封装、接口调用、发票开具、状态回传、数据上报。

(二)技术栈选型

后端采用Spring Boot 2.7.x作为核心框架,整合MyBatis Plus实现数据持久层操作,数据库选用MySQL 8.0存储业务数据,Redis用于缓存热点数据与交易流水。数据采集通信采用Netty框架实现高性能 TCP 协议解析,支持多品牌加油机协议接入。安全层面集成Spring Security + JWT实现身份认证与权限控制,采用Bouncy Castle加密库实现国密 SM2/SM3/SM4 算法。前端采用Vue 3 + Element Plus构建管理后台,提供可视化数据监控与报表展示。

四、核心功能模块与代码实现

(一)加油数据采集模块

数据采集是税控系统的基础,通过 RS-232 串口与加油机通信,按照国家标准协议格式解析数据。以下为核心 Java 代码实现:

// 加油交易数据实体类
@Data
@TableName("fuel_transaction")
public class FuelTransaction {
    @TableId(type = IdType.AUTO)
    private Long id;
    private String stationNo;        // 加油站编号
    private String gunNo;            // 加油枪号
    private String oilType;          // 油品类型
    private BigDecimal volume;       // 加油量(升)
    private BigDecimal unitPrice;    // 单价(元/升)
    private BigDecimal amount;       // 交易金额(元)
    private LocalDateTime tradeTime; // 交易时间
    private String taxControlSn;     // 税控装置序列号
    private String dataSignature;    // 数据签名
    private Integer invoiceStatus;   // 开票状态 0-未开票 1-已开票
    private LocalDateTime createTime;
}

// 加油机数据采集服务
@Service
public class FuelDataCollectorService {

    @Autowired
    private NettyServer nettyServer;
    @Autowired
    private FuelTransactionMapper transactionMapper;
    @Autowired
    private SM4CryptoService sm4CryptoService;

    // 启动数据采集监听
    @PostConstruct
    public void startCollector() {
        nettyServer.bind(8080, new FuelDataDecoder());
    }

    // 解析加油机原始报文
    public FuelTransaction parseRawData(byte[] rawData, String stationNo) {
        FuelTransaction transaction = new FuelTransaction();
        transaction.setStationNo(stationNo);

        // 按国标格式解析:年(4)+月(2)+日(2)+时(2)+分(2)+枪号(2)+油量(10)+金额(10)
        String dataStr = new String(rawData, StandardCharsets.US_ASCII);
        int year = Integer.parseInt(dataStr.substring(0, 4));
        int month = Integer.parseInt(dataStr.substring(4, 6));
        int day = Integer.parseInt(dataStr.substring(6, 8));
        int hour = Integer.parseInt(dataStr.substring(8, 10));
        int minute = Integer.parseInt(dataStr.substring(10, 12));

        transaction.setGunNo(dataStr.substring(12, 14));
        transaction.setVolume(new BigDecimal(dataStr.substring(14, 24)).divide(new BigDecimal("100")));
        transaction.setAmount(new BigDecimal(dataStr.substring(24, 34)).divide(new BigDecimal("100")));
        transaction.setTradeTime(LocalDateTime.of(year, month, day, hour, minute));

        // 生成数据签名防止篡改
        String signature = sm4CryptoService.sign(dataStr);
        transaction.setDataSignature(signature);
        transaction.setInvoiceStatus(0);
        transaction.setCreateTime(LocalDateTime.now());

        return transaction;
    }

    // 数据入库并触发开票流程
    @Transactional
    public void saveAndTriggerInvoice(FuelTransaction transaction) {
        transactionMapper.insert(transaction);
        // 发送消息到开票队列
        invoiceMqProducer.sendInvoiceRequest(transaction.getId());
    }
}

(二)电子发票开具模块

发票开具模块对接税务乐企平台,实现 "交易即开票" 自动化流程。以下为发票开具服务核心代码:

// 发票开具服务
@Service
public class InvoiceService {

    @Autowired
    private LeqiApiClient leqiApiClient;
    @Autowired
    private FuelTransactionMapper transactionMapper;
    @Autowired
    private InvoiceRecordMapper invoiceRecordMapper;

    // 根据交易记录开具电子发票
    @Transactional
    public InvoiceResult issueInvoice(Long transactionId) {
        FuelTransaction transaction = transactionMapper.selectById(transactionId);
        if (transaction == null || transaction.getInvoiceStatus() == 1) {
            return InvoiceResult.fail("交易不存在或已开票");
        }

        // 构建开票请求
        InvoiceRequest request = buildInvoiceRequest(transaction);

        try {
            // 调用乐企平台开票接口
            LeqiResponse response = leqiApiClient.issueInvoice(request);

            if (response.isSuccess()) {
                // 更新交易开票状态
                transaction.setInvoiceStatus(1);
                transactionMapper.updateById(transaction);

                // 保存发票记录
                InvoiceRecord record = new InvoiceRecord();
                record.setTransactionId(transactionId);
                record.setInvoiceNo(response.getInvoiceNo());
                record.setInvoiceCode(response.getInvoiceCode());
                record.setQrCodeUrl(response.getQrCodeUrl());
                record.setPdfUrl(response.getPdfUrl());
                record.setIssueTime(LocalDateTime.now());
                invoiceRecordMapper.insert(record);

                return InvoiceResult.success(response.getInvoiceNo(), response.getQrCodeUrl());
            } else {
                return InvoiceResult.fail(response.getErrorMsg());
            }
        } catch (Exception e) {
            log.error("开票异常,交易ID:{}", transactionId, e);
            return InvoiceResult.fail("开票服务异常");
        }
    }

    // 构建开票请求报文
    private InvoiceRequest buildInvoiceRequest(FuelTransaction transaction) {
        InvoiceRequest request = new InvoiceRequest();
        request.setSellerTaxNo("91XXXXXXXXXXXXXX"); // 销方纳税人识别号
        request.setBuyerTitle("个人");
        request.setInvoiceType("026"); // 数电普票

        // 油品明细行
        InvoiceItem item = new InvoiceItem();
        item.setGoodsName("汽油");
        item.setTaxCode("1070101010000000000"); // 汽油税收编码
        item.setQuantity(transaction.getVolume());
        item.setUnitPrice(transaction.getUnitPrice());
        item.setAmount(transaction.getAmount());
        item.setTaxRate(new BigDecimal("0.13"));

        request.setItems(Collections.singletonList(item));
        request.setTotalAmount(transaction.getAmount());
        request.setRequestNo("INV" + System.currentTimeMillis());

        return request;
    }
}

五、应用案例分析

(一)案例背景

甘肃省临夏州成品油综合服务智慧监管平台是典型的 Java 技术栈税控系统应用案例。该平台于 2025 年 4 月正式上线,覆盖全州 50 户民营加油站及中石油、中石化自营站点,实现了成品油零售数据的全面归集整合。

(二)实施效果

系统部署后,实现了三大核心价值。一是税源监管精准化,通过加油机报税口数据实时采集,税务部门可直接获取真实交易数据,与申报数据自动比对,有效堵塞税收征管漏洞。二是开票效率大幅提升,实现 "交易即开票",车主加油完成后自动收到电子发票,平均开票时间从原来的 3-5 分钟缩短至 3 秒以内。三是风险预警智能化,系统内置异常交易检测算法,对数据异常、设备离线、人为破坏等情况实时报警,2025 年累计预警风险事件 127 起,核查发现涉税问题 32 起。

六、总结与展望

基于 Java 的加油站税控系统通过分层架构设计、标准化数据采集、自动化发票开具,有效解决了传统加油站税收监管中的数据失真、开票滞后、监管缺位等问题。Java 技术栈的成熟稳定性与强安全性,为系统长期可靠运行提供了坚实保障。

未来,随着大数据与人工智能技术的深度应用,加油站税控系统将向智能化方向发展。一方面,引入机器学习算法实现异常交易智能识别,提升税务稽查精准度;另一方面,融合视频 AI 分析、液位仪数据交叉验证,构建 "油、款、单、量" 四位一体的全维度监管体系,进一步推动成品油行业税收治理能力现代化。