lyhzzz 6 天之前
父節點
當前提交
416fc8ede1

+ 8 - 0
README.md

@@ -62,4 +62,12 @@ sceneIds改为numList,取值从场景id改为num。结构从字符串逗号隔
 4.协作相关接口 添加参数sceneType  mesh,laser 
 
 5.findSceneNumber 接口返回添加  sx  key 
+~~~~
+
+~~~~
+1. /user/invoice/open  
+    增加入参 :
+        organizedName  客户名称
+        organizedAddress 客户地址
+        taxRate  税率
 ~~~~

+ 23 - 0
pom.xml

@@ -153,6 +153,29 @@
             <version>2.15.0</version>
         </dependency>
 
+        <dependency>
+            <groupId>com.itextpdf</groupId>
+            <artifactId>itextpdf</artifactId>
+            <version>5.5.9</version>
+        </dependency>
+        <dependency>
+            <groupId>com.itextpdf</groupId>
+            <artifactId>itext-asian</artifactId>
+            <version>5.2.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.aspose</groupId>
+            <artifactId>aspose-cells-fk</artifactId>
+            <version>20.7</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>easyexcel</artifactId>
+            <version>3.1.0</version>
+        </dependency>
+
     </dependencies>
 
     <build>

+ 4 - 1
src/main/java/com/fdkankan/ucenter/common/OssPath.java

@@ -7,5 +7,8 @@ public class OssPath {
     public final static String v3_scenePath = "data/data%s/scene.json";
     public final static String v4_statusPath = "scene_view_data/%s/data/status.json";
     public final static String v4_scenePath = "scene_view_data/%s/data/scene.json";
-    public final static String localStatusPath = System.getProperty("java.io.tmpdir") +"/%s/status.json";   //获取临时文件目录
+    public final static String localPath = "/mnt/ucenter/work";
+    public final static String localStatusPath = localPath +"/%s/status.json";   //获取临时文件目录
+
+
 }

+ 26 - 0
src/main/java/com/fdkankan/ucenter/common/RandomCodeUtil.java

@@ -0,0 +1,26 @@
+package com.fdkankan.ucenter.common;
+
+import java.security.SecureRandom;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class RandomCodeUtil {
+
+    private static final String CHARACTERS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+    private static final SecureRandom random = new SecureRandom();
+    public static synchronized String generateCode(String pre,Integer count) {
+        StringBuilder code = new StringBuilder(pre);
+        for (int i = 0; i < count; i++) {
+            int index = random.nextInt(CHARACTERS.length());
+            code.append(CHARACTERS.charAt(index));
+        }
+
+        return code.toString();
+    }
+
+    public static void main(String[] args) {
+        String format1 = new SimpleDateFormat("yyMMdd").format(new Date());
+        System.out.println(format1);
+        System.out.println(generateCode("W-",8));
+    }
+}

+ 37 - 0
src/main/java/com/fdkankan/ucenter/entity/Invoice.java

@@ -7,7 +7,10 @@ import com.baomidou.mybatisplus.annotation.TableLogic;
 import com.baomidou.mybatisplus.annotation.TableName;
 import java.io.Serializable;
 import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.util.Date;
+
+import com.fdkankan.common.util.SecurityUtil;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -234,5 +237,39 @@ public class Invoice implements Serializable {
     @TableField("invoiced")
     private Integer invoiced;
 
+    @TableField("odd_number")
+    private String oddNumber;
+
+    /**
+     * 发票单号
+     */
+    @TableField("invoice_number")
+    private String invoiceNumber;
+
+    /**
+     * 税率
+     */
+    @TableField("tax_rate")
+    private String taxRate;
+
+    @TableField(exist = false)
+    private String orderSn;
+    @TableField(exist = false)
+    private Integer productCount;
+    @TableField(exist = false)
+    private String productName;
+    @TableField(exist = false)
+    private BigDecimal productMoney;
+    @TableField(exist = false)
+    private String payType;
+
+
+    public BigDecimal getProductMoney() {
+        if(money != null && productCount != null){
+            return money.divide(BigDecimal.valueOf(productCount),2, RoundingMode.UP);
+        }
+        return productMoney;
+    }
+
 
 }

+ 0 - 2
src/main/java/com/fdkankan/ucenter/service/IInvoiceService.java

@@ -34,8 +34,6 @@ public interface IInvoiceService extends IService<Invoice> {
 
     void checkInvoice(Long orderId, Integer consumeType);
 
-    BigDecimal getMoney(Long orderId, Integer consumeType);
-
     JSONObject getMaxInvoice(InvoiceParam param);
 
     PageInfo getInvoices(String token, InvoiceParam param);

+ 85 - 14
src/main/java/com/fdkankan/ucenter/service/impl/InvoiceServiceImpl.java

@@ -3,17 +3,22 @@ package com.fdkankan.ucenter.service.impl;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.fdkankan.common.constant.AppConstant;
 import com.fdkankan.common.constant.ErrorCode;
 import com.fdkankan.common.constant.ServerCode;
 import com.fdkankan.common.constant.TbStatus;
 import com.fdkankan.common.exception.BusinessException;
+import com.fdkankan.ucenter.common.OssPath;
 import com.fdkankan.ucenter.common.PageInfo;
+import com.fdkankan.ucenter.common.RandomCodeUtil;
+import com.fdkankan.ucenter.common.constants.NacosProperty;
 import com.fdkankan.ucenter.entity.*;
 import com.fdkankan.ucenter.mapper.IInvoiceMapper;
 import com.fdkankan.ucenter.service.*;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fdkankan.ucenter.util.MyExcelUtil;
 import com.fdkankan.ucenter.vo.request.InvoiceParam;
 import com.fdkankan.ucenter.vo.request.PlaceOrderParam;
 import com.fdkankan.ucenter.vo.response.OrderVo;
@@ -25,6 +30,8 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Set;
@@ -52,6 +59,8 @@ public class InvoiceServiceImpl extends ServiceImpl<IInvoiceMapper, Invoice> imp
     IExpansionOrderService expansionOrderService;
     @Autowired
     IDownloadOrderService downloadOrderService;
+    @Autowired
+    IMailTemplateService mailTemplateService;
 
     @Override
     public Invoice getByOrderId(Long orderId) {
@@ -142,57 +151,87 @@ public class InvoiceServiceImpl extends ServiceImpl<IInvoiceMapper, Invoice> imp
         }
     }
 
-    @Override
-    public BigDecimal getMoney(Long orderId, Integer consumeType) {
-        LambdaQueryWrapper<Invoice> wrapper = new LambdaQueryWrapper<>();
-        BigDecimal money = BigDecimal.ZERO;
+    public void getMoney(Long orderId, Integer consumeType,Invoice dbEntity) {
+        dbEntity.setMoney(BigDecimal.ZERO);
         switch (consumeType){
             case 0 :
                 Order order = orderService.getById(orderId);
                 if(order.getPaymentStatus().equals("paid")){
-                    money = order.getTotalAmount();
+                    dbEntity.setMoney(order.getTotalAmount());
+                    dbEntity.setOrderSn(order.getOrderSn());
+                    dbEntity.setProductCount(order.getGoodsTotalCount());
+                    dbEntity.setProductName(order.getTradeNum());
+                    dbEntity.setPayType(order.getOrderSn());
                 }
                 break;
             case 1 :
                 VirtualOrder virtualOrder = virtualOrderService.getById(orderId);
                 if(virtualOrder.getPayStatus() == 1){
-                    money = virtualOrder.getAmount();
+                    dbEntity.setMoney(virtualOrder.getAmount());
+                    dbEntity.setOrderSn(virtualOrder.getOrderSn());
+                    dbEntity.setProductCount(virtualOrder.getPoints());
+                    dbEntity.setProductName(virtualOrder.getNumber());
+                    dbEntity.setPayType(virtualOrder.getOrderSn());
                 }
                 break;
             case 2 :
                 IncrementOrder incrementOrder = incrementOrderService.getById(orderId);
                 if(incrementOrder.getPayStatus() == 1){
-                    money = incrementOrder.getAmount();
+                    dbEntity.setMoney(incrementOrder.getAmount());
+                    dbEntity.setOrderSn(incrementOrder.getOrderSn());
+                    dbEntity.setProductCount(incrementOrder.getCount());
+
+                    if("SE".equals(incrementOrder.getMemberLevels())){
+                        dbEntity.setProductName("Senior (Monthly) *" +incrementOrder.getMonthQy());
+                    }else {
+                        dbEntity.setProductName("Premium (Yearly) *" +incrementOrder.getMonthQy());
+                    }
+                    if(incrementOrder.getPayType() ==2 ){
+                        dbEntity.setPayType("paypal");
+                    }
+                    if(incrementOrder.getPayType() ==6 ){
+                        dbEntity.setPayType("stripe");
+                    }
                 }
                 break;
 
             case 3 :
                 DownloadOrder downloadOrder = downloadOrderService.getById(orderId);
                 if(downloadOrder.getPayStatus() == 1){
-                    money = downloadOrder.getAmount();
+                    dbEntity.setMoney(downloadOrder.getAmount());
+                    dbEntity.setOrderSn(downloadOrder.getOrderSn());
+                    dbEntity.setProductCount(downloadOrder.getCount());
+                    dbEntity.setProductName("Scene Download");
+                    if(downloadOrder.getPayType() ==2 ){
+                        dbEntity.setPayType("paypal");
+                    }
+                    if(downloadOrder.getPayType() ==6 ){
+                        dbEntity.setPayType("stripe");
+                    }
                 }
                 break;
         }
-        return money;
     }
 
     @Override
-    public Invoice openInvoice(InvoiceParam param, String token) {
+    public  Invoice openInvoice(InvoiceParam param, String token) {
         User user = userService.getByToken(token);
         //验证是否已经开票
         this.checkInvoice(param.getOrderId(),param.getConsumeType());
         //获取开票金额
-        BigDecimal money = this.getMoney(param.getOrderId(),param.getConsumeType());
 
         Invoice dbEntity = new Invoice();
 
+        this.getMoney(param.getOrderId(),param.getConsumeType(),dbEntity);
+
+
         BeanUtils.copyProperties(param, dbEntity);
 
         dbEntity.setOrderId(null);
         switch (param.getConsumeType()){
             case 0: dbEntity.setOrderId(param.getOrderId()); break;
             case 1: dbEntity.setVirtualOrderId(param.getOrderId()); break;
-            case 2: dbEntity.setIncrementOrderId(param.getOrderId()); break;
+            case 2: dbEntity.setIncrementOrderId(param.getOrderId());break;
             case 3: dbEntity.setDownloadOrderId(param.getOrderId()); break;
         }
 
@@ -200,12 +239,44 @@ public class InvoiceServiceImpl extends ServiceImpl<IInvoiceMapper, Invoice> imp
             dbEntity.setCameraId(param.getCameraId());
         }
         dbEntity.setUserId(user.getId());
-        dbEntity.setMoney(money);
         this.save(dbEntity);
-
+        String invoiceNumber = this.updateInvoiceNumber(dbEntity.getId());
+        dbEntity.setInvoiceNumber(invoiceNumber);
+        sendEmail(dbEntity);
         return dbEntity;
     }
 
+    private void sendEmail(Invoice dbEntity) {
+        //国际服直接发送邮件
+        if("aws".equals(NacosProperty.uploadType)  && dbEntity.getEmailAddress() != null){
+            MailTemplate mailTemplate = mailTemplateService.getTemplate(14, "en");
+            MyExcelUtil.excelTemplteToPdf(OssPath.localPath,"invoiceTemplate",dbEntity);
+            mailTemplateService.sendMail(dbEntity.getEmailAddress(),mailTemplate,"");
+        }
+    }
+
+    private String updateInvoiceNumber(Long id) {
+        String format1 = new SimpleDateFormat("yyMMdd").format(new Date());
+        String invoiceNumber = "W-"+format1 + id;
+        LambdaUpdateWrapper<Invoice> wrapper = new LambdaUpdateWrapper<>();
+        wrapper.eq(Invoice::getId,id);
+        wrapper.set(Invoice::getInvoiceNumber,invoiceNumber);
+        this.update(wrapper);
+        return invoiceNumber;
+    }
+
+    private synchronized String genInVoiceNumber() {
+        String invoiceNumber = RandomCodeUtil.generateCode("W-", 8);
+        LambdaQueryWrapper<Invoice> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(Invoice::getInvoiceNumber,invoiceNumber);
+        List<Invoice> list = this.list(wrapper);
+        if(list == null || list.isEmpty()){
+            return invoiceNumber;
+        }else {
+            return genInVoiceNumber();
+        }
+    }
+
     @Override
     public JSONObject getMaxInvoice(InvoiceParam param) {
         JSONObject object = new JSONObject();

+ 68 - 0
src/main/java/com/fdkankan/ucenter/util/MyExcelUtil.java

@@ -0,0 +1,68 @@
+package com.fdkankan.ucenter.util;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.ExcelWriter;
+import com.alibaba.excel.write.metadata.WriteSheet;
+import com.alibaba.excel.write.metadata.fill.FillConfig;
+import com.fdkankan.fyun.face.FYunFileServiceInterface;
+import com.fdkankan.ucenter.entity.Invoice;
+import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
+import org.apache.poi.xssf.usermodel.XSSFDrawing;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.imageio.ImageIO;
+import javax.servlet.http.HttpServletResponse;
+import java.awt.image.BufferedImage;
+import java.io.*;
+import java.net.URLEncoder;
+import java.util.*;
+
+
+public class MyExcelUtil {
+
+    //根据模板导出excel
+    public static void excelTemplteToPdf(String localPath, String templateName, Object obj) {
+        String fileName = templateName + UUID.randomUUID().toString() + ".xlsx";
+
+        // 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
+        // 填充list 的时候还要注意 模板中{.} 多了个点 表示list
+        //获取文件路径
+        InputStream inputStream = MyExcelUtil.class.getClassLoader().getResourceAsStream("template/"+templateName+ ".xlsx");
+
+        ExcelWriter excelWriter = null;
+
+        String filePath = localPath+File.separator + fileName;
+        excelWriter = EasyExcel.write(filePath)
+                .withTemplate(inputStream)
+                //调用合并策略
+                .autoCloseStream(true)
+                .build();
+        WriteSheet writeSheet = EasyExcel.writerSheet().build();
+        // 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行,然后下面的数据往后移动。默认 是false,会直接使用下一行,如果没有则创建。
+        // forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了,所以慎用
+        // 简单的说 如果你的模板有list,且list不是最后一行,下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存
+        // 如果数据量大 list不是最后一行 参照下一个
+        FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
+        if(excelWriter != null && obj != null){
+            excelWriter.fill(obj, fillConfig, writeSheet);
+        }
+
+        assert excelWriter != null;
+        excelWriter.finish();
+        TestForExcel2PDF.excelToPdf(filePath,filePath.replace(".xlsx",".pdf"));
+
+    }
+
+    public static void main(String[] args) {
+        Invoice invoice = new Invoice();
+        invoice.setInvoiceNumber("11111111111");
+        MyExcelUtil.excelTemplteToPdf("D:\\abc\\1212\\111","invoiceTemplate",invoice);
+    }
+
+}

+ 210 - 0
src/main/java/com/fdkankan/ucenter/util/TestForExcel2PDF.java

@@ -0,0 +1,210 @@
+package com.fdkankan.ucenter.util;
+
+import com.aspose.cells.*;
+import com.itextpdf.awt.geom.Rectangle2D;
+import com.itextpdf.text.BaseColor;
+import com.itextpdf.text.pdf.PdfContentByte;
+import com.itextpdf.text.pdf.PdfReader;
+import com.itextpdf.text.pdf.PdfStamper;
+import com.itextpdf.text.pdf.parser.ImageRenderInfo;
+import com.itextpdf.text.pdf.parser.PdfReaderContentParser;
+import com.itextpdf.text.pdf.parser.RenderListener;
+import com.itextpdf.text.pdf.parser.TextRenderInfo;
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.CtMethod;
+import org.springframework.core.io.ClassPathResource;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+public class TestForExcel2PDF {
+
+    public static void excelToPdf(String xlsxPath,String pdfPath) {
+        excel2pdf(xlsxPath, pdfPath+".sy");
+        replaceStr(pdfPath+".sy",pdfPath,"Evaluation Only. Created with Aspose.Cells for Java.Copyright 2003 - 2022 Aspose Pty Ltd.");
+    }
+
+    private static void replaceStr(String src, String dest, String replaceStr) {
+        try {
+            List<String> resu = new ArrayList<>();
+            PdfReader reader = new PdfReader(src);
+            //获取指定文字的坐标(就是上一步生成的pdf水印)
+            getKeyWords(reader,replaceStr,resu);
+            PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
+            for (int i = 1; i <= resu.size(); i++) {
+                String xy = resu.get(i - 1);
+                PdfContentByte canvas = stamper.getOverContent(i);
+                canvas.saveState();
+                //设置颜色
+                canvas.setColorFill(BaseColor.WHITE);
+                //解析坐标
+                double x = Double.valueOf(xy.split("--")[0]);
+                double y = Double.valueOf(xy.split("--")[1]) - 10;
+                //后面2个参数分别是宽高
+                canvas.rectangle(x, y, 450, 100);
+                canvas.fill();
+                canvas.restoreState();
+            }
+            stamper.close();
+            reader.close();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 获取指定文字的坐标
+     */
+    public static void getKeyWords(PdfReader pdfReader, String replaceStr,List<String> resu ) {
+        try {
+            int pageNum = pdfReader.getNumberOfPages();
+            PdfReaderContentParser pdfReaderContentParser = new PdfReaderContentParser(
+                    pdfReader);
+            for (int i = 1; i <= pageNum; i++) {
+                pdfReaderContentParser.processContent(i, new RenderListener() {
+                    @Override
+                    public void renderText(TextRenderInfo textRenderInfo) {
+                        String text = textRenderInfo.getText(); // 整页内容
+                        if (null != text && text.contains(replaceStr)) {
+                            Rectangle2D.Float boundingRectange = textRenderInfo
+                                    .getBaseline().getBoundingRectange();
+                            String xy = boundingRectange.x + "--" + boundingRectange.y;
+                            resu.add(xy);
+                        }
+                    }
+                    @Override
+                    public void renderImage(ImageRenderInfo arg0) {
+                    }
+                    @Override
+                    public void endTextBlock() {
+                    }
+                    @Override
+                    public void beginTextBlock() {
+                    }
+                });
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 获取license 去除水印
+     * @return
+     */
+    public static void getLicense() {
+        try {
+            ClassPathResource classPathResource = new ClassPathResource("/com.aspose.cells.lic_2999.xml");
+            InputStream license = classPathResource.getInputStream();
+            License aposeLic = new License();
+            aposeLic.setLicense(license);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * excel 转为pdf 输出。
+     *
+     * @param sourceFilePath  excel文件
+     * @param desFilePathd  pad 输出文件目录
+     */
+    public static void excel2pdf(String sourceFilePath, String desFilePathd ){
+        getLicense();
+        try {
+            Workbook wb = new Workbook(sourceFilePath);// 原始excel路径
+//            IndividualFontConfigs configs = new IndividualFontConfigs();
+//            configs.setFontFolder("/usr/share/fonts/chinese", true);
+//            LoadOptions loadOptions  = new LoadOptions();
+//            loadOptions.setFontConfigs(configs);
+
+            FileOutputStream fileOS = new FileOutputStream(desFilePathd);
+            PdfSaveOptions pdfSaveOptions = new PdfSaveOptions();
+            pdfSaveOptions.setOnePagePerSheet(true);
+
+
+            int[] autoDrawSheets={3};
+            //当excel中对应的sheet页宽度太大时,在PDF中会拆断并分页。此处等比缩放。
+//            autoDraw(wb,autoDrawSheets);
+
+            int[] showSheets={0};
+            //隐藏workbook中不需要的sheet页。
+            printSheetPage(wb,showSheets);
+            wb.save(fileOS, pdfSaveOptions);
+            fileOS.flush();
+            fileOS.close();
+            System.out.println("完毕");
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+
+    /**
+     * 设置打印的sheet 自动拉伸比例
+     * @param wb
+     * @param page 自动拉伸的页的sheet数组
+     */
+    public static void autoDraw(Workbook wb,int[] page){
+        if(null!=page&&page.length>0){
+            for (int i = 0; i < page.length; i++) {
+                wb.getWorksheets().get(i).getHorizontalPageBreaks().clear();
+                wb.getWorksheets().get(i).getVerticalPageBreaks().clear();
+            }
+        }
+    }
+
+
+    /**
+     * 隐藏workbook中不需要的sheet页。
+     * @param wb
+     * @param page 显示页的sheet数组
+     */
+    public static void printSheetPage(Workbook wb,int[] page){
+        for (int i= 1; i < wb.getWorksheets().getCount(); i++)  {
+            wb.getWorksheets().get(i).setVisible(false);
+        }
+        if(null==page||page.length==0){
+            wb.getWorksheets().get(0).setVisible(true);
+        }else{
+            for (int i = 0; i < page.length; i++) {
+                wb.getWorksheets().get(i).setVisible(true);
+            }
+        }
+    }
+
+    public static void crackAspose(String JarPath, String outPath) throws Exception {
+        // 这个是得到反编译的池
+        ClassPool pool = ClassPool.getDefault();
+
+        // 取得需要反编译的jar文件,设定路径
+        pool.insertClassPath(JarPath);
+
+        CtClass cc_License = pool.get("com.aspose.cells.License");
+
+        CtMethod method_isLicenseSet = cc_License.getDeclaredMethod("isLicenseSet");
+        method_isLicenseSet.setBody("return true;");
+
+        CtClass cc_License2 = pool.get("com.aspose.cells.License");
+        CtMethod method_setLicense = cc_License2.getDeclaredMethod("setLicense");
+        method_setLicense.setBody("{    a = new com.aspose.cells.License();\n" +
+                "    com.aspose.cells.zbiw.a();}");
+
+        CtMethod method_k = cc_License.getDeclaredMethod("k");
+        method_k.setBody("return new java.util.Date(Long.MAX_VALUE);");
+
+        cc_License.writeFile(outPath);
+    }
+
+    public static void main(String[] args) throws Exception{
+        crackAspose("D:\\sale\\aspose-cells-20.7.jar","D:\\sale");
+    }
+
+}
+
+

二進制
src/main/resources/template/invoiceTemplate.xlsx