航天增值税记录

21 篇文章 1 订阅
9 篇文章 0 订阅

一、准备工作

  • 引入xfire
<dependency>
	<groupId>org.codehaus.xfire</groupId>
	<artifactId>xfire-core</artifactId>
	<version>1.2</version>
</dependency>
<dependency>
	<groupId>org.codehaus.xfire</groupId>
	<artifactId>xfire-aegis</artifactId>
	<version>1.2</version>
</dependency>
  • 引入Freemarker模板
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

二、编写业务代码

  • 编写获取模板内容工具类
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import org.springframework.util.ResourceUtils;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class FreemarkerUtils {
	
	/**
	 * 读取freemarkers模板
	 * @param path 模板所在目录(template/模板名称.html)
	 * @param model 模板要跳出的数据
	 * @return
	 */
	public static String randeHtml(String path,Map<String, Object> model) {
		try {
			StringWriter stringWriter = new StringWriter();
			try {
				Configuration cfg = new Configuration(Configuration.VERSION_2_3_28);
				
				模板所在目录 这里是放在resources/templates目录下
				String templatePath = ResourceUtils.getURL("classpath:templates/xml").getPath();
				cfg.setLocale(Locale.CHINA);
				cfg.setEncoding(Locale.CHINA, "UTF-8");
				cfg.setDefaultEncoding("UTF-8");
				cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
				cfg.setLogTemplateExceptions(false);
				cfg.setWrapUncheckedExceptions(true);
				cfg.setClassicCompatible(true);
				cfg.setTagSyntax(Configuration.AUTO_DETECT_TAG_SYNTAX);
				cfg.setWhitespaceStripping(true);
				
				cfg.setDirectoryForTemplateLoading(new File(templatePath));
				
				Template temp = cfg.getTemplate(path);
				
				temp.process(model, stringWriter);
				
				stringWriter.flush();
				return stringWriter.toString();
			} catch (Exception e) {
				log.error(e.getMessage());
				try {
					stringWriter.close();
				} catch (IOException ex) {
					log.error(e.getMessage());
				}
			}
		} catch (Exception e) {
			// TODO: handle exception
		}
		return null;
	}
	
}

此工具类用来获取模板html文件报文

  • 创建模板文件(报文)
<?xml version='1.0' encoding='UTF-8'?>
<interface version='DZFP1.0'>
    <globalInfo>
        <terminalCode>${terminalCode}</terminalCode>
        <appId>${appId}</appId>
        <version>${version}</version>
        <interfaceCode>${interfaceCode}</interfaceCode>
        <userName>${userName}</userName>
        <passWord>${passWord}</passWord>
        <taxpayerId>${taxpayerId}</taxpayerId>
        <authorizationCode>${authorizationCode}</authorizationCode>
        <requestCode>${requestCode}</requestCode>
        <requestTime>${requestTime}</requestTime>
        <responseCode/>
        <dataExchangeId>${dataExchangeId}</dataExchangeId>
    </globalInfo>
    <returnStateInfo>
        <returnCode/>
        <returnMessage/>
    </returnStateInfo>
    <Data>
        <dataDescription>
            <zipCode>${zipCode}</zipCode>
            <encryptCode>${encryptCode}</encryptCode>
            <codeType>${codeType}</codeType>
        </dataDescription>
        <content>${content}</content>
    </Data>
</interface>
<REQUEST_FPKJXX class="REQUEST_FPKJXX">
    <FPKJXX_FPTXX class="FPKJXX_FPTXX">
        <FPQQLSH>${FPQQLSH}</FPQQLSH>
        <DSPTBM>${DSPTBM}</DSPTBM>
        <NSRSBH>${NSRSBH}</NSRSBH>
        <NSRMC>${NSRMC}</NSRMC>
        <NSRDZDAH/>
        <SWJG_DM/>
        <DKBZ>${DKBZ}</DKBZ>
        <SGBZ/>
        <PYDM>${PYDM}</PYDM>
        <KPXM>${KPXM}</KPXM>
        <BMB_BBH>${BMB_BBH}</BMB_BBH>
        <XHF_NSRSBH>${XHF_NSRSBH}</XHF_NSRSBH>
        <XHFMC>${XHFMC}</XHFMC>
        <XHF_DZ>${XHF_DZ}</XHF_DZ>
        <XHF_DH>${XHF_DH}</XHF_DH>
        <XHF_YHZH>${XHF_YHZH}</XHF_YHZH>
        <GHFMC>${GHFMC}</GHFMC>
        <GHF_NSRSBH/>
        <GHF_SF/>
        <GHF_DZ>${GHF_DZ}</GHF_DZ>
        <GHF_GDDH>${GHF_GDDH}</GHF_GDDH>
        <GHF_SJ>${GHF_SJ}</GHF_SJ>
        <GHF_EMAIL/>
        <GHFQYLX>${GHFQYLX}</GHFQYLX>
        <GHF_YHZH/>
        <HY_DM/>
        <HY_MC/>
        <KPY>${KPY}</KPY>
        <SKY>${SKY}</SKY>
        <FHR>${FHR}</FHR>
        <KPRQ>${KPRQ}</KPRQ>
        <KPLX>${KPLX}</KPLX>
        <YFP_DM/>
        <YFP_HM/>
        <CZDM>${CZDM}</CZDM>
        <QD_BZ>${QD_BZ}</QD_BZ>
        <QDXMMC/>
        <CHYY/>
        <TSCHBZ>${TSCHBZ}</TSCHBZ>
        <KPHJJE>${KPHJJE}</KPHJJE>
        <HJBHSJE>${HJBHSJE}</HJBHSJE>
        <HJSE>${HJSE}</HJSE>
        <BZ>${BZ}</BZ>
        <BYZD1/>
        <BYZD2/>
        <BYZD3/>
        <BYZD4/>
        <BYZD5/>
    </FPKJXX_FPTXX>
    <FPKJXX_XMXXS class="FPKJXX_XMXX;" size="${itemSize}">
        <#list items as item>
        <FPKJXX_XMXX>
            <XMMC>${item.XMMC}</XMMC>
            <XMDW>${item.XMDW}</XMDW>
            <GGXH>${item.GGXH}</GGXH>
            <XMSL>${item.XMSL}</XMSL>
            <HSBZ>${item.HSBZ}</HSBZ>
            <XMDJ>${item.XMDJ}</XMDJ>
            <FPHXZ>${item.FPHXZ}</FPHXZ>
            <SPBM>${item.SPBM}</SPBM>
            <ZXBM/>
            <YHZCBS>${item.YHZCBS}</YHZCBS>
            <LSLBS/>
            <ZZSTSGL/>
            <KCE/>
            <XMJE>${item.XMJE}</XMJE>
            <SL>${item.SL}</SL>
            <SE>${item.SE}</SE>
            <BYZD1/>
            <BYZD2/>
            <BYZD3/>
            <BYZD4/>
            <BYZD5/>
        </FPKJXX_XMXX>
        </#list>
    </FPKJXX_XMXXS>
    <FPKJXX_DDXX class="FPKJXX_DDXX">
        <DDH/>
        <THDH/>
        <DDDATE/>
    </FPKJXX_DDXX>
    <FPKJXX_DDMXXXS class="FPKJXX_DDMXXX;" size="1">
        <FPKJXX_DDMXXX>
            <DDMC/>
            <DW/>
            <GGXH/>
            <SL/>
            <DJ/>
            <JE/>
            <BYZD1/>
            <BYZD2/>
            <BYZD3/>
            <BYZD4/>
            <BYZD5/>
        </FPKJXX_DDMXXX>
    </FPKJXX_DDMXXXS>
    <FPKJXX_ZFXX class="FPKJXX_ZFXX">
        <ZFFS/>
        <ZFLSH/>
        <ZFPT/>
    </FPKJXX_ZFXX>
    <FPKJXX_WLXX class="FPKJXX_WLXX">
        <CYGS/>
        <SHSJ/>
        <WLDH/>
        <SHDZ/>
    </FPKJXX_WLXX>
</REQUEST_FPKJXX>
  • 编写工具类AisinoUtil

import java.beans.Encoder;
import java.math.BigInteger;
import java.net.MalformedURLException;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.codehaus.xfire.client.XFireProxyFactory;
import org.codehaus.xfire.service.Service;
import org.codehaus.xfire.service.binding.ObjectServiceFactory;

import com.zhixuan.common.utils.DateUtils;
import com.zhixuan.common.utils.SerialNumberUtils;
import com.zhixuan.modules.vat.config.AisinoConfig;
import com.zhixuan.modules.vat.dto.RecordsDTO;

public class AisinoUtils {

	/**
	 * 生成PassWord
	 * @return
	 */
	public static String generatePassWord(){
		String passWord = null;
		String s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
		StringBuilder sBuilder = new StringBuilder();
		Random random = new Random();
		for (int i = 0; i < 10; i++) {
			int ran = random.nextInt(s.length());
			sBuilder.append(s.charAt(ran));
		}
		String rString = sBuilder.toString();
		sBuilder.append(AisinoConfig.REGISTER_CODE);
		final String md5String = getMD5String(sBuilder.toString());
		final Base64.Encoder encoder = Base64.getEncoder();
		try {
			passWord = rString+encoder.encodeToString(md5String.getBytes());
		} catch (Exception e) {
			e.printStackTrace();
		}
		return passWord;
	}
	
	/**
	 * 航天开具发票(异步)
	 * 内层报文
	 * @param dto
	 * @return
	 */
	public static String makeContent(RecordsDTO dto) {
		Map<String, Object> model = new HashMap<String, Object>();
		model.put("FPQQLSH", dto.getSerialNumber());//发票请求唯一流水号
		model.put("DSPTBM", AisinoConfig.TERRACE_CODE);//平台编码
		model.put("NSRSBH", dto.getMerchant().getTaxNumber());//开票方识别号
		model.put("NSRMC", dto.getMerchant().getName());//开票方名称
		model.put("NSRDZDAH", "");//开票方电子档案号
		model.put("SWJG_DM", "");//税务机构代码
		model.put("DKBZ", "0");//代开标志
//		model.put("SGBZ", "");//收购标志
		model.put("PYDM", AisinoConfig.INVOICE_CODE);//票样代码
		model.put("KPXM", dto.getRecordsList().get(0).getCommodityName());//主要开票项目
		model.put("BMB_BBH", AisinoConfig.CODE_VERSION);//编码表版本号
		model.put("XHF_NSRSBH", AisinoConfig.TAXPAYER_REGISTRATION_CODE);//销货方识别号
		model.put("XHFMC", dto.getMerchant().getName());//销货方名称
		model.put("XHF_DZ", dto.getMerchant().getAddress());//销货方地址
		model.put("XHF_DH", dto.getMerchant().getTel());//销货方电话
		model.put("XHF_YHZH", dto.getMerchant().getBankName()+dto.getMerchant().getBankAccount());//销货方银行账号
		model.put("GHFMC", dto.getClienteleName());//购货方名称
//		model.put("GHF_NSRSBH", "");//购货方识别号
//		model.put("GHF_SF", "");//购货方省份
		model.put("GHF_DZ", dto.getClienteleAddress());//购货方地址
		model.put("GHF_GDDH", dto.getClienteleTel());//购货方固定电话
		model.put("GHF_SJ", "15000000000");//购货方手机
//		model.put("GHF_EMAIL", "");//购货方邮箱
		model.put("GHFQYLX", "01");//购货方企业类型 01:企业  02:机关事业单位 03:个人       04:其它 
//		model.put("GHF_YHZH", "");//购货方银行账号
//		model.put("HY_DM", "");//行业代码
//		model.put("HY_MC", "");//行业名称
		model.put("KPY", dto.getPayee());//开票员
		model.put("SKY", dto.getReview());//收款员
		model.put("FHR", dto.getDrawer());//复核人
		model.put("KPRQ", DateUtils.format(new Date(), DateUtils.DATE_TIME_PATTERN));//开票日期
		model.put("KPLX", "1");//开票类型 1 正票 2 红票 
//		model.put("YFP_DM", "");//原发票代码
//		model.put("YFP_HM", "");//原发票号码
		model.put("CZDM", "10");//操作代码  10 正票正常开具、 11 正票错票重开、 20 退货折让红票、       21 错票重开红票、 
		model.put("QD_BZ", "0");//清单标志 0 正常冲红或正常       蓝票开具(电子发 35. TSCHBZ 特殊冲红标志 CHAR 1 是 票) 1 特殊冲红(冲红纸       质等) 
//		model.put("QDXMMC", "");//清单发票项目名称 清单标识(QD_BZ)       为 1 时必填000000
//		model.put("CHYY", "");//冲红原因
		model.put("TSCHBZ", "0");//特殊冲红标志
		model.put("KPHJJE", dto.getCommodityAmount());//价税合计金额
		model.put("HJBHSJE", dto.getAmount());//合计不含税金额
		model.put("HJSE", dto.getTaxAmount());//合计税额
		model.put("BZ", ".");//备注
		
		model.put("itemSize", dto.getRecordsList().size());//子项目长度
		List<Map<String, String>> items = new ArrayList<>();
		dto.getRecordsList().forEach(i -> {
			Map<String, String> item = new HashMap<String, String>();
			
			item.put("XMMC", i.getCommodityName());//项目名称
			item.put("XMDW", i.getUnitMeasurement());//项目单位
			item.put("GGXH", i.getSpecifications());//规格型号
			item.put("XMSL", i.getNumber().intValue()+"");//项目数量
			item.put("HSBZ", i.getTaxFlag() ? "1":"0");//含税标志
			System.out.println(i.getUnitPrice());
			item.put("XMDJ", i.getUnitPrice().toString());//项目单价
			item.put("FPHXZ", "0");//发票行性质 0 正常行、 1 折扣行、 2 被折扣行 
			item.put("SPBM", "1100301010000000000");//商品编码
			item.put("YHZCBS", i.getPreferentialPolicyFlag() ? "1":"0");//优惠政策标识
//			item.put("LSLBS", "0");//零税率标识
//			item.put("ZZSTSGL", "出口零税 ");//增值税特殊管理
//			item.put("KCE", "");//扣除额
			item.put("XMJE", i.getCommodityAmount().toString());//项目金额
			item.put("SL", i.getTaxRate().toString());//税率
			item.put("SE", i.getTaxAmount().toString());//税额
			items.add(item);
		});
		model.put("items", items);//明细集合
		
//		model.put("DDH", "");//订单号
//		model.put("THDH", "");//退货单号
//		model.put("DDDATE", "");//订单时间
//		model.put("DDMC", "1");//订单名称
//		model.put("DW", "1");//单位
//		model.put("GGXH", "1");//规格型号
//		model.put("SL", "1");//数量
//		model.put("DJ", "1");//单价
//		model.put("JE", "1");//金额end
//		model.put("ZFFS", "1");//支付方式
//		model.put("ZFLSH", "1");//支付流水号
//		model.put("ZFPT", "1");//支付平台end
//		model.put("CYGS", "1");//承运公司
//		model.put("SHSJ", "1");//送货时间
//		model.put("WLDH", "1");//物流单号
//		model.put("SHDZ", "1");//送货地址
		
		return formatBase64(FreemarkerUtils.randeHtml("make.html", model));
	}
	
	/**
	 * 航天接口外层报文
	 * @param dto
	 * @param content
	 * @return
	 */
	public static String outer(RecordsDTO dto,String content) {
		Map<String, Object> model = new HashMap<String, Object>();
		model.put("terminalCode", AisinoConfig.BS);//终端类型标识
		model.put("appId", AisinoConfig.ELECTRONIC_INVOICE);//固定为:DZFP 表示普通发票。ZZS_PT_DZFP 表示增值税普通电子发票 
		model.put("version", AisinoConfig.INTERFACE_VERSION);//接口版本号
		model.put("interfaceCode", AisinoConfig.MAKE);//接口编码
		model.put("userName", dto.getClienteleName());//用户编码
		model.put("passWord", AisinoUtils.generatePassWord());//
		model.put("taxpayerId", AisinoConfig.TAXPAYER_REGISTRATION_CODE);//纳税人识别号
		model.put("authorizationCode", AisinoConfig.AUTHORIZTION_CODE);//接入系统平台授权码(由服务商提供)
		model.put("requestCode", dto.getClienteleName());//数据交换请求发出方代码
		model.put("requestTime", DateUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss SS"));//数据交换请求发出时间
		model.put("dataExchangeId", SerialNumberUtils.generateDataSerialNumber());//数据交换流水号
		model.put("zipCode", AisinoConfig.ZERO);// (0,1根据数据包大小判断是否进行压缩) 
		model.put("encryptCode", AisinoConfig.ZERO);//(加密方式代码) 
		model.put("codeType", AisinoConfig.BASE64);//(加密方式代码,正式使用时通讯用CA) 
		model.put("content", content);//base64请求数据内容或返回数据内容
		return FreemarkerUtils.randeHtml("outer.html", model);
	}
	
	/**
	 * 航天开具发票(异步)
	 * @param dto
	 * @return
	 */
	public static String invoiceMake(RecordsDTO dto) {
		return outer(dto, AisinoUtils.makeContent(dto));
	}
	
	/**
	 * MD5加密
	 * @param str
	 * @return
	 */
	public static String getMD5String(String str) {
        try {
            // 生成一个MD5加密计算摘要
            MessageDigest md = MessageDigest.getInstance("MD5");
            // 计算md5函数
            md.update(str.getBytes());
            // digest()最后确定返回md5 hash值,返回值为8位字符串。因为md5 hash值是16位的hex值,实际上就是8位的字符
            // BigInteger函数则将8位的字符串转换成16位hex值,用字符串来表示;得到字符串形式的hash值
            //一个byte是八位二进制,也就是2位十六进制字符(2的8次方等于16的2次方)
            return new BigInteger(1, md.digest()).toString(16);
        } catch (Exception e) {
           e.printStackTrace();
           return null;
        }
    }
	
	/**
	 * base64加密
	 * @param text
	 * @return
	 */
	public static String formatBase64(String text) {
		Base64.Encoder encoder = Base64.getEncoder();
		try {
			return encoder.encodeToString(text.getBytes("UTF-8"));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return text;
	}
	
	/**
	 * base64解密
	 * @param text
	 * @return
	 */
	public static String parseBase64(String text) {
		Base64.Decoder decoder = Base64.getDecoder();
		try {
			return new String(decoder.decode(text),"UTF-8");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return text;
	}
	
}
  • 发送报文
	@Override
	public InvoiceResponseDTO invoiceMake(RecordsDTO dto) {
		String xml = AisinoUtils.invoiceMake(dto);
		try {
			Client client = new Client(new URL("接口uri"));
			Object[] resultObjects = client.invoke("接口代码", new Object[]{xml});
			System.out.println(resultObjects[0].toString());
		} catch (Exception e) {
			e.printStackTrace();
		}
		return responseDTO;
	}

注意:写报文不要放过任何细节,一个空格都可能解析失败。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值