You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Spring Boot生成PNG/JPG格式发票并发送至手机号的技术方案咨询

基于Spring Boot实现发票图片生成与短信发送方案

一、发票图片生成的可行方案

1. 直接基于模板图片填充文字(最适配现有模板)

这种方式通过Java原生的BufferedImage API操作现有模板图片,在指定坐标位置绘制发票字段内容,无需额外依赖,开发成本低,适合固定格式的简单模板。

核心步骤:

  • 用图片工具(如Photoshop、系统画图工具)定位每个发票字段的坐标(x,y)。
  • 读取模板图片,通过Graphics2D对象绘制文字,设置字体、颜色、对齐方式。
  • 保存生成后的图片为PNG/JPG格式。

示例代码:

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class TemplateBasedInvoiceGenerator {
    public static void generate(String templatePath, String outputPath) throws IOException {
        // 加载发票模板图片
        BufferedImage templateImg = ImageIO.read(new File(templatePath));
        Graphics2D g2d = templateImg.createGraphics();

        // 配置字体(确保支持中文,避免乱码)
        Font textFont = new Font("SimSun", Font.PLAIN, 14);
        g2d.setFont(textFont);
        g2d.setColor(Color.BLACK);
        // 开启抗锯齿,让文字更清晰
        g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

        // 填充发票字段(坐标需根据实际模板调整)
        g2d.drawString("发票编号:INV20240520001", 160, 90);
        g2d.drawString("客户名称:某某科技有限公司", 160, 135);
        g2d.drawString("开票日期:2024-05-20", 480, 135);
        g2d.drawString("合计金额:¥1,200.00", 480, 380);

        // 释放绘图资源
        g2d.dispose();

        // 保存为PNG格式
        ImageIO.write(templateImg, "PNG", new File(outputPath));
    }
}

2. HTML模板引擎转图片(灵活适配复杂模板)

如果发票样式需要频繁调整,或者包含复杂排版(如表格、动态样式),推荐用Thymeleaf/Freemarker生成HTML发票页面,再通过工具将HTML转为图片。这种方式通过CSS控制样式,维护成本低,扩展性强。

核心依赖:

  • Thymeleaf:用于生成动态HTML
  • Flying Saucer:将HTML/CSS渲染为图片

示例步骤:

  1. 引入Maven依赖:
<dependencies>
    <dependency>
        <groupId>org.thymeleaf</groupId>
        <artifactId>thymeleaf-spring6</artifactId>
        <version>3.1.2.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.xhtmlrenderer</groupId>
        <artifactId>flying-saucer-core</artifactId>
        <version>9.1.22</version>
    </dependency>
</dependencies>
  1. 编写Thymeleaf模板(templates/invoice.html):
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <style>
        .invoice-container { width: 800px; padding: 20px; border: 1px solid #ccc; }
        .invoice-header { text-align: center; margin-bottom: 30px; }
        .invoice-info { display: flex; justify-content: space-between; margin-bottom: 20px; }
        .amount { font-size: 18px; font-weight: bold; color: #e63946; }
    </style>
</head>
<body>
    <div class="invoice-container">
        <div class="invoice-header">
            <h2>增值税普通发票</h2>
        </div>
        <div class="invoice-info">
            <div>
                <p>发票编号:<span th:text="${invoiceNo}"></span></p>
                <p>客户名称:<span th:text="${customerName}"></span></p>
            </div>
            <div>
                <p>开票日期:<span th:text="${invoiceDate}"></span></p>
            </div>
        </div>
        <div class="amount">合计金额:¥<span th:text="${totalAmount}"></span></div>
    </div>
</body>
</html>
  1. 生成HTML并转图片:
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.xhtmlrenderer.swing.Java2DRenderer;
import java.awt.image.BufferedImage;
import java.io.FileOutputStream;
import javax.imageio.ImageIO;

public class HtmlToInvoiceImageGenerator {
    public static void generate(TemplateEngine templateEngine, String outputPath) throws Exception {
        Context context = new Context();
        context.setVariable("invoiceNo", "INV20240520001");
        context.setVariable("customerName", "某某科技有限公司");
        context.setVariable("invoiceDate", "2024-05-20");
        context.setVariable("totalAmount", "1,200.00");

        // 渲染生成HTML字符串
        String htmlContent = templateEngine.process("invoice", context);

        // 将HTML转为图片(设置宽高适配发票尺寸)
        Java2DRenderer renderer = new Java2DRenderer(htmlContent, 800, 1100);
        BufferedImage invoiceImage = renderer.getImage();

        // 保存图片
        ImageIO.write(invoiceImage, "PNG", new FileOutputStream(outputPath));
    }
}

3. PDF转图片(兼顾多格式输出)

如果业务需要同时生成PDF版和图片版发票,可先通过iText生成PDF发票,再用Apache PDFBox将PDF转为图片。这种方式适合需要多格式存档的场景。

核心依赖:

  • iText:生成PDF
  • Apache PDFBox:PDF转图片

二、图片发票的短信发送实现

由于直接通过短信发送图片受运营商限制,推荐先将生成的发票图片上传至云存储(如阿里云OSS、腾讯云COS),再发送图片访问链接到指定手机号。

以阿里云短信为例,核心代码示例:

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.profile.DefaultProfile;

public class InvoiceSmsSender {
    public static void sendInvoiceLink(String phoneNumber, String imageUrl) throws Exception {
        // 初始化短信客户端
        DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", "你的AccessKeyId", "你的AccessKeySecret");
        IAcsClient client = new DefaultAcsClient(profile);

        // 构建短信请求
        SendSmsRequest request = new SendSmsRequest();
        request.setPhoneNumbers(phoneNumber);
        request.setSignName("你的短信签名");
        request.setTemplateCode("你的短信模板ID");
        request.setTemplateParam("{\"invoiceUrl\":\"" + imageUrl + "\"}");

        // 发送短信
        SendSmsResponse response = client.getAcsResponse(request);
        // 根据response处理发送结果(如判断是否发送成功)
    }
}

三、最优方案选择

  • 固定简单模板:优先选择「模板图片填充文字」方案,依赖少、开发快、性能高。
  • 复杂/动态样式模板:优先选择「HTML模板引擎转图片」方案,通过CSS控制样式,维护成本低。
  • 需要多格式输出:选择「PDF转图片」方案,兼顾PDF存档和图片发送需求。

内容的提问来源于stack exchange,提问作者Beksultan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 07:12:03