java 实现生成公司的电子公章,并且盖章生成电子合同

前言

  1. 以下方法大多数是博主从网上查阅资料参考很多大神的方法之后,然后结合博主的理解,将大神们的方法整理实现的,还有不少方法忘记参考的哪位大佬的了,所以目前仅是将想起来的大神提供出来,如有侵权请联系博主删除。未经博主同意,暂不给转载哈。
  2. 以下出现的公司名称原本是博主的公司,现在已注销了,如有侵权请联系博主删除。

参考大佬们的代码:(部分)
JAVA利用Graphics2D生成电子签章
修改Jar包中的内容(替换、删除文件)+ aspose-words签名解除 + 配置maven引入

一、生成电子公章工具类

电子公章效果如图:
java 实现生成公司的电子公章,并且盖章生成电子合同_第1张图片

工具类如下:(直接拷贝可用,已根据博主需要做了一下细微调整)

package com.siboo.util;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;

import com.newtec.myqdp.server.utils.StringUtils;
 
public class Graphics2DUtil {
    
    private static final int WIDTH = 450;//图片宽度
    private static final int HEIGHT = 450;//图片高度
    
    /**
     * 
    * @Title: splitImage
    * @Description: 分割图片
    * @param image 图片BufferedImage流
    * @param rows 分割行
    * @param cols 分割列
    * @return BufferedImage[] 返回分割后的图片流
     */
    public static BufferedImage[] splitImage(BufferedImage image, int rows, int cols) {
        // 分割成4*4(16)个小图
        int chunks = rows * cols;
        // 计算每个小图的宽度和高度
        int chunkWidth = image.getWidth() / cols + 3;// 向右移动3
        int chunkHeight = image.getHeight() / rows;
        int count = 0;
        BufferedImage[] imgs = new BufferedImage[chunks];
        for (int x = 0; x < rows; x++) {
            for (int y = 0; y < cols; y++) {
                //设置小图的大小和类型
                imgs[count] = new BufferedImage(chunkWidth, chunkHeight, BufferedImage.TYPE_INT_RGB);
                //写入图像内容
                Graphics2D gr = imgs[count].createGraphics();
                // 增加下面代码使得背景透明  
                imgs[count] = gr.getDeviceConfiguration().createCompatibleImage(chunkWidth, chunkHeight, Transparency.TRANSLUCENT);
//                gr.setBackground(Color.WHITE);// 背景为白色
//                 // 加上这句才算真正将背景颜色设置为透明色
//                gr.clearRect(0, 0,chunkWidth,chunkHeight);
                gr.dispose();
                gr = imgs[count].createGraphics();
                gr.drawImage(image, 0, 0,
                        chunkWidth, chunkHeight,
                        chunkWidth * y, chunkHeight * x,
                        chunkWidth * y + chunkWidth,
                        chunkHeight * x + chunkHeight, null);
                gr.dispose();
                count++;
            }
        }
        return imgs;
    }
    
    /**
     * 
    * @Title: startGraphics2D
    * @Description: 生成公司电子公章
    * @param message 公司名称
    * @param centerName 公章类型,如:测试章
    * @param year 时间
    * @return BufferedImage 返回类型
     */
    public static BufferedImage startGraphics2D(String message, String centerName, String year){
        // 定义图像buffer         
        BufferedImage buffImg = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);         
        Graphics2D g = buffImg.createGraphics();   
        // 增加下面代码使得背景透明  
        buffImg = g.getDeviceConfiguration().createCompatibleImage(WIDTH, HEIGHT, Transparency.TRANSLUCENT);  
        g.dispose();  
        g = buffImg.createGraphics();  
        // 背景透明代码结束 
        g.setColor(Color.RED);
        //设置锯齿圆滑
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        //绘制圆
        int radius = HEIGHT/3;//周半径
        int CENTERX = WIDTH/2;//画图所出位置
        int CENTERY = HEIGHT/2;//画图所处位置
        
        Ellipse2D circle = new Ellipse2D.Double();
        circle.setFrameFromCenter(CENTERX, CENTERY, CENTERX + radius, CENTERY + radius);
        g.setStroke(new BasicStroke(10));//设置圆的宽度
        g.draw(circle);
        
        int num = 120;
        int num1 = 40;
//        num = 90;
        num1 = 72;
        
        //绘制中间的五角星
        g.setFont(new Font("宋体", Font.BOLD, num));
        g.drawString("★", CENTERX-(num/2), CENTERY+(num/3));    
 
        //添加姓名
        g.setFont(new Font("宋体", Font.LAYOUT_LEFT_TO_RIGHT, 30));// 写入签名
        g.drawString(centerName, CENTERX -(num1), CENTERY +(30+50));
        
        //添加年份
        g.setFont(new Font("宋体", Font.LAYOUT_LEFT_TO_RIGHT, 20));// 写入签名
        g.drawString(year, CENTERX -(66), CENTERY +(30+78));
        
        //根据输入字符串得到字符数组
        char[] messages = message.toCharArray();
        
        //输入的字数
        int ilength = messages.length;
        
        //设置字体属性
        int fontsize = 40;
        Font f = new Font("Serif", Font.BOLD, fontsize);
 
        FontRenderContext context = g.getFontRenderContext();
        Rectangle2D bounds = f.getStringBounds(message, context);
        
        //字符宽度=字符串长度/字符数
        double char_interval = (bounds.getWidth() / ilength);
        //上坡度
        double ascent = -bounds.getY() + 3;
 
        int first = 0,second = 0;
        boolean odd = false;
        if (ilength%2 == 1) {
            first = (ilength-1)/2;
            odd = true;
        } else {
            first = (ilength)/2-1;
            second = (ilength)/2;
            odd = false;
        }
        
        double radius2 = radius - ascent;
        double x0 = CENTERX;
        double y0 = CENTERY - radius + ascent;
        //旋转角度
        double a = 2*Math.asin(char_interval/(2*radius2));
        
        if (odd) {
            g.setFont(f);
            g.drawString(StringUtils.toString(messages[first]), (float)(x0 - char_interval/2), (float)y0);
            
            //中心点的右边
            for (int i=first+1;i<ilength;i++)
            {
                double aa = (i - first) * a;
                double ax = radius2 * Math.sin(aa);
                double ay = radius2 - radius2 * Math.cos(aa);
                AffineTransform transform = AffineTransform.getRotateInstance(aa);//,x0 + ax, y0 + ay);
                Font f2 = f.deriveFont(transform);
                g.setFont(f2);
                g.drawString(StringUtils.toString(messages[i]), (float)(x0 + ax - char_interval/2* Math.cos(aa)), (float)(y0 + ay - char_interval/2* Math.sin(aa)));
            }
            //中心点的左边
            for (int i=first-1;i>-1;i--)
            {
                double aa = (first - i) * a;
                double ax = radius2 * Math.sin(aa);
                double ay = radius2 - radius2 * Math.cos(aa);
                AffineTransform transform = AffineTransform.getRotateInstance(-aa);//,x0 + ax, y0 + ay);
                Font f2 = f.deriveFont(transform);
                g.setFont(f2);
                g.drawString(StringUtils.toString(messages[i]), (float)(x0 - ax - char_interval/2* Math.cos(aa)), (float)(y0 + ay + char_interval/2* Math.sin(aa)));
            }
            
        } else {
            //中心点的右边
            for (int i=second;i<ilength;i++)
            {
                double aa = (i - second + 0.5) * a;
                double ax = radius2 * Math.sin(aa);
                double ay = radius2 - radius2 * Math.cos(aa);
                AffineTransform transform = AffineTransform.getRotateInstance(aa);//,x0 + ax, y0 + ay);
                Font f2 = f.deriveFont(transform);
                g.setFont(f2);
                g.drawString(StringUtils.toString(messages[i]), (float)(x0 + ax - char_interval/2* Math.cos(aa)), (float)(y0 + ay - char_interval/2* Math.sin(aa)));
            }
            
            //中心点的左边
            for (int i=first;i>-1;i--)
            {
                double aa = (first - i + 0.5) * a;
                double ax = radius2 * Math.sin(aa);
                double ay = radius2 - radius2 * Math.cos(aa);
                AffineTransform transform = AffineTransform.getRotateInstance(-aa);//,x0 + ax, y0 + ay);
                Font f2 = f.deriveFont(transform);
                g.setFont(f2);
                g.drawString(StringUtils.toString(messages[i]), (float)(x0 - ax - char_interval/2* Math.cos(aa)), (float)(y0 + ay + char_interval/2* Math.sin(aa)));
            }
        }
        
        return buffImg;
    }


}

调用方法如下:

public static void main(String[] args) throws Exception{
    	Date dNow = new Date( );
		SimpleDateFormat ft = new SimpleDateFormat ("yyyy年MM月dd日");
		String year = ft.format(dNow);
        BufferedImage image = startGraphics2D("广州思博商贸有限公司","合同专用章",year);
        
        String filePath = "";
        try {
            filePath = "F:\\BaiduNetdiskDownload\\"+new Date().getTime()+".png";
            ImageIO.write(image, "png", new File(filePath)); //将其保存在D:\\下,得有这个目录
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

二、由word模板生成电子合同PDF文件,并盖章

1.对word文档操作的工具类如下:

package com.siboo.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;

import com.aspose.words.License;
import com.newtec.myqdp.server.utils.StringUtils;


public class WordUtil {
	
    /**
     *   
    * @Title: replaceAndGenerateWord
    * @Description: 替换word中需要替换的特殊字符
    * 优化后是为了分别减少map遍历,增加性能,前提是表格的替换的数据不一样,所以将两者分离处理(加空间,提性能)
    * @param srcPath 需要替换的文档全路径
    * @param destPath 替换后文档的保存路径
    * @param contentMap {key:将要被替换的内容,value:替换后的内容}
    * @param replaceTableMap {key:将要被替换的表格内容,value:替换后的表格内容}
    * @return boolean 返回成功状态
     */
    public static boolean replaceAndGenerateWord(String  srcPath, String exportFile, Map<String, String> contentMap, Map<String, String> replaceTableMap) {
    	boolean bool = true;
        try {
        	FileInputStream inputStream = new FileInputStream(srcPath);
        	XWPFDocument document = new XWPFDocument(inputStream);
            // 替换段落中的指定文字
            Iterator<XWPFParagraph> itPara = document.getParagraphsIterator();
            while (itPara.hasNext()) {
                XWPFParagraph paragraph = itPara.next();
                commonCode(paragraph, contentMap);
            }
            // 替换表格中的指定文字
            Iterator<XWPFTable> itTable = document.getTablesIterator();
            while (itTable.hasNext()) {
                XWPFTable table = itTable.next();
                int rcount = table.getNumberOfRows();
                for (int i = 0; i < rcount; i++) {
                    XWPFTableRow row = table.getRow(i);
                    List<XWPFTableCell> cells = row.getTableCells();
                    for (XWPFTableCell cell : cells) {
                        //单元格中有段落,得做段落处理
                        List<XWPFParagraph> paragraphs = cell.getParagraphs();
                        for (XWPFParagraph paragraph : paragraphs) {
                            commonCode(paragraph, replaceTableMap);
                        }
                    }
                }
            }

            FileOutputStream outStream = new FileOutputStream(exportFile);
            document.write(outStream);
            outStream.close();
            inputStream.close();
        }catch (Exception e){
        	bool = false;
            e.printStackTrace();
        }
        return bool;
    }
    
    /**
     * 
    * @Title: commonCode
    * @Description: 替换内容
    * @param paragraph 被替换的文本信息
    * @param contentMap {key:将要被替换的内容,value:替换后的内容}
     */
    private static void commonCode(XWPFParagraph paragraph,Map<String, String> contentMap){
        List<XWPFRun> runs = paragraph.getRuns();
        for (XWPFRun run : runs) {
            String oneparaString = run.getText(run.getTextPosition());
            if (StringUtils.isStrNull(oneparaString)){
                continue;
            }
            for (Map.Entry<String, String> entry : contentMap.entrySet()) {
                oneparaString = oneparaString.replace(entry.getKey(), StringUtils.isStrNull(entry.getValue()) ? "--" : entry.getValue());
            }
            run.setText(oneparaString, 0);
        }
    }
    
    /**
     * 
    * @Title: getLicense
    * @Description:验证license许可凭证
    * @return boolean 返回验证License状态
     */
    private static boolean getLicense() {
        boolean result = true;
        try {
//        	new License().setLicense(new FileInputStream(new File("D:\\develop\\template\\license.xml").getAbsolutePath()));
            new License().setLicense(new FileInputStream(new File(FilesUtil.getLicensePath()).getAbsolutePath()));
        } catch (Exception e) {
        	result = false;
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 
    * @Title: wordConverterToPdf
    * @Description: word转pdf(aspose转换)
    * @param wordPath word 全路径,包括文件全称
    * @param pdfPath pdf 保存路径,包括文件全称
    * @return boolean 返回转换状态
     */
    public static boolean wordConverterToPdf(String wordPath, String pdfPath) {
    	System.out.println("===================aspose开始转换=======================");
    	//开始时间
    	long start = System.currentTimeMillis();
    	boolean bool = false;
    	// 验证License,若不验证则转化出的pdf文档会有水印产生
        if (!getLicense()) return bool;
        try {
            FileOutputStream os = new FileOutputStream(new File(pdfPath));// 新建一个pdf文档输出流
            com.aspose.words.Document doc = new com.aspose.words.Document(wordPath);// Address是将要被转化的word文档
            doc.save(os, com.aspose.words.SaveFormat.PDF);// 全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF, EPUB, XPS, SWF 相互转换
            os.close();
            bool = true;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
        	System.out.println("(aspose)word转换PDF完成,用时"+(System.currentTimeMillis()-start)/1000.0+"秒");
		}
        return bool;
    }

    /**
     * 
    * @Title: wordConverterToPdfJacob
    * @Description: word转pdf(jacob转换)
    * @param wordFile word 全路径,包括文件全称
    * @param pdfFile pdf 保存路径,包括文件全称
    * @return boolean 返回转换状态
     */
//    public static boolean wordConverterToPdfJacob(String wordFile, String pdfFile) {
//		System.out.println("===================jacob开始转换=======================");
//		//开始时间
//		long start = System.currentTimeMillis();  
//		ActiveXComponent app = new ActiveXComponent("Word.Application");// 创建对象,花了很长时间
//		boolean bool = false;
//		try {
//			// 打开word
//			// 获得word中所有打开的文档
//			Dispatch documents = app.getProperty("Documents").toDispatch();
			System.out.println("打开文件: " + wordFile);
//			// 打开文档
//			Dispatch document = Dispatch.call(documents, "Open", wordFile, false, true).toDispatch();
//			// 如果文件存在的话,不会覆盖,会直接报错,所以我们需要判断文件是否存在
//			File target = new File(pdfFile);
//			if (target.exists()) {
//				target.delete();
//			}
			System.out.println("另存为: " + pdfFile);
//			Dispatch.call(document, "SaveAs", pdfFile, 17);
//			// 关闭文档
//			Dispatch.call(document, "Close", false);
//			bool = true;
//		} catch (Exception e) {
//			System.out.println("转换失败" + e.getMessage());
//		} finally {
//			// 关闭office
//			app.invoke("Quit", 0);
//			System.out.println("生成完成,用时"+(System.currentTimeMillis()-start)/1000.0+"秒");
//		}
//		return bool;
//    }
    
    /**
	 * 
	* @Title: insertRow
	* @Description: 在word表格中指定位置插入一行,并将某一行的样式复制到新增行
	* @param table 需要插入的表格
	* @param copyrowIndex 需要复制的行位置
	* @param newrowIndex 需要新增一行的位置
	* @return void 返回类型
	 */
	public static void insertRow(XWPFTable table, int copyrowIndex, int newrowIndex) {
		// 在表格中指定的位置新增一行
		XWPFTableRow targetRow = table.insertNewTableRow(newrowIndex);
		// 获取需要复制行对象
		XWPFTableRow copyRow = table.getRow(copyrowIndex);
		//复制行对象
		targetRow.getCtRow().setTrPr(copyRow.getCtRow().getTrPr());
		//或许需要复制的行的列
		List<XWPFTableCell> copyCells = copyRow.getTableCells();
		//复制列对象
		XWPFTableCell targetCell = null;
		for (int i = 0; i < copyCells.size(); i++) {
			XWPFTableCell copyCell = copyCells.get(i);
			targetCell = targetRow.addNewTableCell();
			targetCell.getCTTc().setTcPr(copyCell.getCTTc().getTcPr());
			if (copyCell.getParagraphs() != null && copyCell.getParagraphs().size() > 0) {
				targetCell.getParagraphs().get(0).getCTP().setPPr(copyCell.getParagraphs().get(0).getCTP().getPPr());
				if (copyCell.getParagraphs().get(0).getRuns() != null
						&& copyCell.getParagraphs().get(0).getRuns().size() > 0) {
					XWPFRun cellR = targetCell.getParagraphs().get(0).createRun();
					cellR.setBold(copyCell.getParagraphs().get(0).getRuns().get(0).isBold());
				} 
			} 
		}
		
	}
	
}   

2.生成电子合同

	String id = "?";// 合同id,根据自己需求
	// 合同保存路径
	String contractPath = FilesUtil.getContract();
	// 电子合同临时保存路径
	StringBuilder temporaryPath = new StringBuilder(contractPath)
			.append("temporary");
	// 判断临时文件夹是否存在,不存在则新建
	File file = new File(temporaryPath.toString());
	if (!file.exists()) {
		file.mkdirs();
	}
	temporaryPath.append(File.separator).append(id).append(".docx");
	// 1、  查询合同信息(该方法省略,具体看自己的需求)
	Map<String, String> replaceMap = getContractData(contractService,id, temporaryPath.toString());
	String userNum = replaceMap.get("userNum");
	StringBuilder destPathDOCX = new StringBuilder(contractPath)
	.append(userNum);
	// 判断用户文件夹是否存在,不存在则新建
	File userNumFile = new File(destPathDOCX.toString());
	if (!userNumFile.exists()) {
		userNumFile.mkdirs();
	}
	destPathDOCX.append(File.separator).append(id).append(".docx");
	//            	        StringBuilder savePath = new StringBuilder(userNum)
	//            	        		.append(File.separator).append(id).append(".pdf");
	Map<String, String> replaceTableMap = new HashMap<String, String>();
	replaceTableMap.put("totalAmount", replaceMap.remove("totalAmount"));
	replaceTableMap.put("totalCapitalizeAmount", replaceMap.remove("totalCapitalizeAmount"));
	// 2、  替换合同里面的参数
	WordUtil.replaceAndGenerateWord(temporaryPath.toString(), destPathDOCX.toString(), replaceMap, replaceTableMap);
	
	StringBuilder pdfFile = new StringBuilder(contractPath)
			.append(userNum).append(File.separator).append(id).append(".pdf");
	// 3、将word转pdf文件
	Boolean bool = WordUtil.wordConverterToPdf(destPathDOCX.toString(), pdfFile.toString());
	if (!bool) {
	map.put("msg", "合同word转pdf文件失败");
	return;
	}
	// 4.1 删除临时电子合同
	File temporaryPathDOCX = new File(temporaryPath.toString());
	if (temporaryPathDOCX.exists()) {
	temporaryPathDOCX.delete();
	}
	// 4.2 删除word电子合同
	File fileDOCX = new File(destPathDOCX.toString());
	if (fileDOCX.exists()) {
	fileDOCX.delete();
	}

电子合同效果(pdf文件)
java 实现生成公司的电子公章,并且盖章生成电子合同_第2张图片

3.电子合同盖章

/**
	 * 
	* @Title: itextPDFAddPicture
	* @Description: 为pdf加图片(电子合同盖公章)
	* @param inputStream 电子合同pdf文件流
	* @param map {company:公司公章名称,purpose:公章用途,year:日期}
	* @param targetPath 保存路径
	* @throws Exception 异常参数
	 */
	public static void itextPDFAddPicture(InputStream inputStream, Map<String, String> map, String targetPath) throws Exception{
		// 1.1 读取模板文件
        PdfReader reader = new PdfReader(inputStream);
        // 1.2 创建文件输出流
        FileOutputStream out = new FileOutputStream(targetPath);
        // 2、创建PdfStamper对象
        PdfStamper stamper = new PdfStamper(reader, out);
        // 3、设置公章信息
        String company = FilesUtil.getDefaultCompany();// 公司公章名称
        String purpose = FilesUtil.getDefaultPurpose();// 公章用途
        String year = map.get("year");// 日期
        if (StringUtils.isStrNull(year)) {
        	year = new SimpleDateFormat (FilesUtil.getContractTimeFormat()).format(new Date());
        }
        // 4、生成公章
        BufferedImage bufferedImage = Graphics2DUtil.startGraphics2D(company, purpose, year);// 整个公章图片流
        BufferedImage[] imgs = Graphics2DUtil.splitImage(bufferedImage, 1, 2);
        BufferedImage leftBufferedImage = imgs[0];// 左边公章图片流
        BufferedImage rightBufferedImage = imgs[1];// 右边公章图片流
        
        // 5、读公章图片
        Image image = Image.getInstance(imageToBytes(bufferedImage));
        Image leftImage = Image.getInstance(imageToBytes(leftBufferedImage));
        Image rightImage = Image.getInstance(imageToBytes(rightBufferedImage));
        int chunkWidth = 200;// 公章大小,x轴
        int chunkHeight = 200;// 公章大小,y轴
        // 获取pdf页面的高和宽
        Rectangle pageSize = reader.getPageSize(1);
        float height = pageSize.getHeight();
        float width = pageSize.getWidth();
        // 6、为pdf每页加印章
        // 设置公章的位置
        float xL = width - chunkWidth/2 - 2;
        float yL = height/2-chunkHeight/2-25;
        
        float xR = width-chunkHeight/2 + chunkHeight/8 + 4;
        float yR = yL;
        // 6.1 第一页盖左章
        leftImage.scaleToFit(chunkWidth, chunkHeight);// 公章大小
        leftImage.setAbsolutePosition(xL, yL);// 公章位置
        // 6.2 第二页盖右章
    	rightImage.scaleToFit(chunkWidth, chunkHeight);// 公章大小
        rightImage.setAbsolutePosition(xR, yR);// 公章位置
        int pdfPages = reader.getNumberOfPages();// pdf页面页码
        // 遍历为每页盖左章或右章
        for (int i = 1; i <= pdfPages; i++) {
        	if (i % 2 == 0) {// 盖右章
        		stamper.getOverContent(i).addImage(rightImage);
        	} else {// 盖左章
        		stamper.getOverContent(i).addImage(leftImage);
        	}
		}
        
        // 6.3 最后一页盖公章
    	image.scaleToFit(chunkWidth, chunkWidth);
    	image.setAbsolutePosition(width/2 + 32, height-chunkHeight + 20);
    	stamper.getOverContent(pdfPages).addImage(image);
    	
    	// 7、关闭相关流
        stamper.close();
        out.close();
        reader.close();
        inputStream.close();
	}

盖章效果如下:
java 实现生成公司的电子公章,并且盖章生成电子合同_第3张图片

java 实现生成公司的电子公章,并且盖章生成电子合同_第4张图片

4.补充

配置文件:
java 实现生成公司的电子公章,并且盖章生成电子合同_第5张图片
license.xml

<License>
    <Data>
        <Products>
            <Product>Aspose.Total for JavaProduct>
            <Product>Aspose.Words for JavaProduct>
        Products>
        <EditionType>EnterpriseEditionType>
        <SubscriptionExpiry>20991231SubscriptionExpiry>
        <LicenseExpiry>20991231LicenseExpiry>
        <SerialNumber>8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7SerialNumber>
    Data>
    <Signature>sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=Signature>
License>

合同模板.docx
java 实现生成公司的电子公章,并且盖章生成电子合同_第6张图片
所需相关jar包
在这里插入图片描述
链接:https://pan.baidu.com/s/12ysaXaJ0XfRj4MUXwaIUXA
提取码:ar8a

总结

此贴是博主第一次写博,还存在很多不足之处,后期会慢慢完善,如果有不理解之处可以联系博主哈,也欢迎各路大神过来一起探讨。

你可能感兴趣的:(电子合同,电子公章,盖章,java,itext)