创建javabean ,RequestCommonFPKJ
@XStreamAlias("REQUEST_COMMON_FPKJ")
public class RequestCommonFPKJ {
@XStreamAsAttribute //子元素作为标签属性出现
@XStreamAlias("class") //标签别名
private String classBQ;
//发票内容
@XStreamAlias("COMMON_FPKJ_FPT")
private COMMON_FPKJ_FPT COMMON_FPKJ_FPT;
//项目信息(发票明细)(多条)
//@XStreamImplicit
@XStreamAlias("COMMON_FPKJ_XMXXS")
private COMMON_FPKJ_XMXXS COMMON_FPKJ_XMXXS;
//setter、getter
}
创建javabean COMMON_FPKJ_FPT
@XStreamAlias("COMMON_FPKJ_FPT")
public class COMMON_FPKJ_FPT{
@XStreamAsAttribute
@XStreamAlias("calss")
private String classBQ;
@XStreamAlias("FPQQLSH")
private String FPQQLSH; //发票请求流水号
@XStreamAlias("DDH")
private String DDH; //订单号
@XStreamAlias("KPLX")
private String KPLX; //开票类型
@XStreamAlias("BMB_BBH")
private String BMB_BBH; //编码表版本号
@XStreamAlias("XSF_NSRSBH")
private String XSF_NSRSBH; //销售方纳税人识别号
@XStreamAlias("XSF_MC")
private String XSF_MC; //销售方名称
@XStreamAlias("XSF_DZDH")
private String XSF_DZDH; //销售方地址、电话
@XStreamAlias("XSF_YHZH")
private String XSF_YHZH; //销售方银行账号
@XStreamAlias("GMF_NSRSBH")
private String GMF_NSRSBH; //购买方纳税人识别号
@XStreamAlias("GMF_MC")
private String GMF_MC; //购买方名称
@XStreamAlias("GMF_DZDH")
private String GMF_DZDH; //购买方地址、电话
@XStreamAlias("GMF_YHZH")
private String GMF_YHZH; //购买方银行账号
@XStreamAlias("GMF_SJ")
private String GMF_SJ; //购买方手机
@XStreamAlias("GMF_EMAIL")
private String GMF_EMAIL; //购买方邮箱
@XStreamAlias("KPR")
private String KPR; //开票人
@XStreamAlias("SKR")
private String SKR; //收款人
@XStreamAlias("FHR")
private String FHR; //复核人
@XStreamAlias("YFP_DM")
private String YFP_DM; //原发票代码
@XStreamAlias("YFP_HM")
private String YFP_HM; //原发票号码
@XStreamAlias("JSHJ")
private String JSHJ; //价税合计
@XStreamAlias("HJJE")
private String HJJE; //合计金额
@XStreamAlias("HJSE")
private String HJSE; //合计税额
@XStreamAlias("BZ")
private String BZ; //备注
//setter\getter...
}
创建javabean COMMON_FPKJ_XMXXS
@XStreamAlias("COMMON_FPKJ_XMXXS")
public class COMMON_FPKJ_XMXXS {
@XStreamAsAttribute
@XStreamAlias("class")
private String classBQ;
@XStreamAsAttribute
@XStreamAlias("size")
private Integer size;
@XStreamImplicit
private List<COMMON_FPKJ_XMXX> commonFpkjXmxxs;
//setter、getter...
}
创建javabean COMMON_FPKJ_XMXX
@XStreamAlias("COMMON_FPKJ_XMXX")
public class COMMON_FPKJ_XMXX{
@XStreamAlias("FPHXZ")
private String FPHXZ; //发票行性质
@XStreamAlias("SPBM")
private String SPBM; //商品编码
@XStreamAlias("ZXBM")
private String ZXBM; //自行编码
@XStreamAlias("YHZCBS")
private String YHZCBS; //优惠政策标识
@XStreamAlias("LSLBS")
private String LSLBS; //零税率标识
@XStreamAlias("ZZSTSGL")
private String ZZSTSGL; //增值税特殊管理
@XStreamAlias("XMMC")
private String XMMC; //项目名称
@XStreamAlias("GGXH")
private String GGXH; //规格型号
@XStreamAlias("DW")
private String DW; //单位
@XStreamAlias("XMSL")
private String XMSL; //项目数量
@XStreamAlias("XMDJ")
private String XMDJ; //项目单价
@XStreamAlias("XMJE")
private String XMJE; //项目金额
@XStreamAlias("SL")
private String SL; //税率
@XStreamAlias("SE")
private String SE; //税额
//setter、getter...
}
工具类XmlUtils、XStreamDateConverter
package com.vincce.whhy.common.entity.util;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.basic.*;
import com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder;
import com.thoughtworks.xstream.io.xml.XppDriver;
import com.vincce.whhy.common.entity.third.ticket.ReturnStateInfo;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import java.text.SimpleDateFormat;
import java.util.Iterator;
import java.util.Map;
import java.util.TimeZone;
/**
*
* @author carlee
*
*/
public class XmlUtils {
/**
*
* @param claz
* @param xmlMessage
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T convertXml2JavaBean(Class<T> claz, String xmlMessage) {
XStream xStream = new XStream();
xStream.processAnnotations(claz);
String XMLMessage = StringEscapeUtils.unescapeXml(xmlMessage); //特殊转义字符处理
xStream.registerConverter(new XStreamDateConverter("yyyy-MM-dd HH:mm:ss", null, TimeZone.getTimeZone("GMT+8")));
xStream.registerConverter(new XStreamDateConverter("yyyy-MM-ddTHH:mm:ssZ", null, TimeZone.getTimeZone("GMT+8")));
xStream.registerConverter(new StringConverter() {
@Override
public String fromString(String str) {
if (StringUtils.isEmpty(str)) {
return null;
}
return super.fromString(str).toString().trim();
}
});
// 下面是转换常用的数字类型
xStream.registerConverter(new DoubleConverter() {
@Override
public Object fromString(String str) {
if (StringUtils.isEmpty(str)) {
return null;
}
return super.fromString(str);
}
});
xStream.registerConverter(new LongConverter() {
@Override
public Object fromString(String str) {
if (StringUtils.isEmpty(str)) {
return null;
}
return super.fromString(str);
}
});
xStream.registerConverter(new IntConverter() {
@Override
public Object fromString(String str) {
if (StringUtils.isEmpty(str)) {
return null;
}
if ("FALSE".equals(str)) {
return 0;
}
if ("TRUE".equals(str)) {
return 1;
}
return super.fromString(str);
}
});
xStream.registerConverter(new BigDecimalConverter() {
@Override
public Object fromString(String str) {
if (StringUtils.isEmpty(str)) {
return null;
}
return super.fromString(str);
}
});
T t = (T) xStream.fromXML(XMLMessage);
return t;
}
/**
*
* @param claz
* @param xmlMessage
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T convertXml2JavaBean(Class<T> claz, String xmlMessage, String dataFormat) {
XStream xStream = new XStream();
xStream.processAnnotations(claz);
xStream.registerConverter(new DateConverter(dataFormat, null));
T t = (T) xStream.fromXML(xmlMessage);
return t;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public static String bean2xml(Map<String, Class> clazzMap, Object bean) {
XStream xStream = new XStream();
for (Iterator it = clazzMap.entrySet().iterator(); it.hasNext();) {
Map.Entry<String, Class> m = (Map.Entry<String, Class>) it.next();
xStream.alias(m.getKey(), m.getValue());
}
String xml = xStream.toXML(bean);
return xml;
}
public static String bean2xml(Object bean) {
//XStream xStream = new XStream();
//属性名中_(下划线)处理
XStream xStream = new XStream(new XppDriver(new XmlFriendlyNameCoder("_-", "_")));
xStream.autodetectAnnotations(true);
String xmlTemp = xStream.toXML(bean);
String xml = StringEscapeUtils.unescapeXml(xmlTemp);
return xml;
}
public static void main(String[] args) throws Exception {
String str = "<returnStateInfo>\n" +
"<returnCode>9999</returnCode>\n" +
"<returnMessage>6K+35rGCWE1M5oql5paH5Li656m677yB</returnMessage>\n" +
"</returnStateInfo>";
ReturnStateInfo returnStateInfo = convertXml2JavaBean(new ReturnStateInfo().getClass(), str);
System.out.println(returnStateInfo.toString());
String time = "2015-01-12T15:17:02+08:00";
SimpleDateFormat date = new SimpleDateFormat("yyyy-MM-dd'T'hh:ss:mm");
System.out.println(date.parse(time));
}
}
package com.vincce.whhy.common.entity.util;
import com.thoughtworks.xstream.converters.basic.DateConverter;
import org.apache.commons.lang3.StringUtils;
import java.util.Locale;
import java.util.TimeZone;
public class XStreamDateConverter extends DateConverter {
public XStreamDateConverter() {
super();
}
public XStreamDateConverter(boolean lenient) {
super(lenient);
}
public XStreamDateConverter(String defaultEraFormat, String defaultFormat, String[] acceptableFormats, Locale locale, TimeZone timeZone, boolean lenient) {
super();
}
public XStreamDateConverter(String defaultFormat, String[] acceptableFormats, boolean lenient) {
super(defaultFormat, acceptableFormats, lenient);
}
public XStreamDateConverter(String defaultFormat, String[] acceptableFormats, TimeZone timeZone, boolean lenient) {
super(defaultFormat, acceptableFormats, timeZone, lenient);
}
public XStreamDateConverter(String defaultFormat, String[] acceptableFormats, TimeZone timeZone) {
super(defaultFormat, acceptableFormats, timeZone);
}
public XStreamDateConverter(String defaultFormat, String[] acceptableFormats) {
super(defaultFormat, acceptableFormats);
}
public XStreamDateConverter(TimeZone timeZone) {
super(timeZone);
}
@Override
public Object fromString(String str) {
if (StringUtils.isEmpty(str)) {
return null;
}
return super.fromString(str);
}
}
webservice接口访问类
package com.vincce.whhy.common.entity.third.util;
import com.alibaba.fastjson.JSONObject;
import com.hooks.hooksspringbootstarter.util.StringUtils;
import com.vincce.whhy.common.entity.third.constant.TicketConstant;
import com.vincce.whhy.common.entity.third.sms.SmsRequest;
import com.vincce.whhy.common.entity.third.ticket.*;
import com.vincce.whhy.common.entity.util.Base64Utils;
import com.vincce.whhy.common.entity.util.XmlUtils;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.lang.StringEscapeUtils;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
/**
*
*/
public class TicketUtil {
private String namespace;
private String methodName;
private String wsdlLocation;
private String soapResponseData;
public TicketUtil(String namespace, String methodName,
String wsdlLocation) {
this.namespace = namespace;
this.methodName = methodName;
this.wsdlLocation = wsdlLocation;
}
private int invoke(Map<String, Object> patameterMap) throws Exception {
PostMethod postMethod = new PostMethod(wsdlLocation);
String soapRequestData = buildRequestData(patameterMap);
System.out.println("请求URl:" + wsdlLocation);
System.out.println("请求xml内容======================开始");
System.out.println(soapRequestData);
System.out.println("请求xml内容======================结束");
byte[] bytes = soapRequestData.getBytes("utf-8");
InputStream inputStream = new ByteArrayInputStream(bytes, 0,
bytes.length);
RequestEntity requestEntity = new InputStreamRequestEntity(inputStream,
bytes.length, "text/xml; charset=utf-8");
postMethod.setRequestEntity(requestEntity);
HttpClient httpClient = new HttpClient();
int statusCode = httpClient.executeMethod(postMethod);
soapResponseData = postMethod.getResponseBodyAsString();
//System.out.println(soapResponseData);
return statusCode;
}
/**
*
* @param patameterMap
* @return
*/
private String buildRequestData(Map<String, Object> patameterMap) {
StringBuffer soapRequestData = new StringBuffer();
//测试请求xml内容
soapRequestData.append("<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><soap:Body><eiInterface xmlns=\"http://ws.aisino.com\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n");
soapRequestData.append(map2XmlContent(patameterMap,new StringBuilder()));
soapRequestData.append("</eiInterface></soap:Body>");
soapRequestData.append("</soap:Envelope>");
return soapRequestData.toString();
}
/**
* 递归map组装请求xml中的Content
* @param patameterMap
* @param xmlContentString
* @return
*/
private String map2XmlContent(Map<String, Object> patameterMap,StringBuilder xmlContentString){
xmlContentString.append(XmlUtils.bean2xml(patameterMap.get("globalInfo")));
xmlContentString.append(XmlUtils.bean2xml(patameterMap.get("returnStateInfo")));
xmlContentString.append(XmlUtils.bean2xml(patameterMap.get("Data")));
return xmlContentString.toString();
}
/**
* 发票开具接口
* @return
*/
public static Object test2(TicketRequest bean,RequestCommonFPKJ beanData,String env){
try {
TicketUtil ticketUtil = new TicketUtil(TicketConstant.NAMESPACE, TicketConstant.METHOD_NAME, "pro".equals(env)?TicketConstant.WSDL_LOCATION_PRO:TicketConstant.WSDL_LOCATION_DEV);
Map<String, Object> patameterMap = new HashMap<>();
TicketRequest ticketRequest = buildContentData(bean, beanData);
patameterMap.put("globalInfo", ticketRequest.getGlobalInfo());
patameterMap.put("returnStateInfo", ticketRequest.getReturnStateInfo());
patameterMap.put("Data", ticketRequest.getData());
int statusCode = TicketConstant.IS_TEST?200:ticketUtil.invoke(patameterMap);
if(statusCode == 200) {
String resultXML = ticketUtil.soapResponseData;
System.out.println("调用短信发送成功!");
System.out.println("返回xml内容======================开始");
System.out.println(resultXML);
System.out.println("返回xml内容======================结束");
if(TicketConstant.IS_TEST){
//resultXML = "<?xml version=\"1.0\" encoding=\"utf-8\"?><S:Envelope xmlns:S=\"http://schemas.xmlsoap.org/soap/envelope/\"><S:Body><eiInterfaceResponse xmlns=\"http://ws.aisino.com\"><out><interface xmlns=\"\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><globalInfo><version/><interfaceCode/><taxpayerId/><authorizationCode/></globalInfo><returnStateInfo><returnCode>9999</returnCode><returnMessage>6K+35rGCWE1M5oql5paH5Li656m677yB</returnMessage></returnStateInfo><Data><dataDescription><zipCode>0</zipCode><encryptCode/><codeType/></dataDescription><content/></Data></interface></out></eiInterfaceResponse></S:Body></S:Envelope>";
}
System.out.println("开票调用结果======");
//返回xml解析
JSONObject jsonObject = restult2bean(resultXML);
return jsonObject;
}else {
System.out.println("开票调用失败!错误码:" + statusCode);
return "开票调用失败";
}
}catch (Exception e){
e.printStackTrace();
return "开票调用异常";
}
}
/**
* 返回xml解析
* @param resultXML
* @return
*/
private static JSONObject restult2bean(String resultXML){
JSONObject jsonObj = new JSONObject();
String[] returnStateInfos = resultXML.split("returnStateInfo");
String returnStateInfoXml = "<returnStateInfo"+returnStateInfos[1]+"returnStateInfo>";
ReturnStateInfo returnStateInfo = XmlUtils.convertXml2JavaBean(new ReturnStateInfo().getClass(), returnStateInfoXml);
try {
//返回信息解码
returnStateInfo.setReturnMessage(Base64Utils.decodeBase64Str(returnStateInfo.getReturnMessage()));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
if("0000".equals(returnStateInfo.getReturnCode())){
String[] contents = returnStateInfos[2].split("RESPONSE_COMMON_FPKJ");
String contentXml = "<RESPONSE_COMMON_FPKJ" + contents[2].substring(1,contents[2].length()) + "RESPONSE_COMMON_FPKJ>";
ResponseCommonFPKJ responseCommonFPKJ = XmlUtils.convertXml2JavaBean(new ResponseCommonFPKJ().getClass(), contentXml);
jsonObj.put("responseCommonFPKJ", responseCommonFPKJ);
jsonObj.put("returnStateInfo",returnStateInfo);
} else {
jsonObj.put("returnStateInfo",returnStateInfo);
}
return jsonObj;
}
/**
* 组装入参xml中content内容
* @param bean
* @param beanData
* @return
*/
private static TicketRequest buildContentData(TicketRequest bean,RequestCommonFPKJ beanData){
String fpkjData = XmlUtils.bean2xml(beanData);
Data data = bean.getData();
data.setContent(fpkjData);
return bean;
}
}
rest接口
@RestController
@RequestMapping("/v1/invoice")
public class InvoiceController {
@GetMapping("/test")
@ResponseBody
public ResultEntity test(HttpServletRequest request, String env){
System.out.println("调用开票系统开始===");
TicketRequest bean = new TicketRequest();
bean.setGlobalInfo(new GlobalInfo());
bean.setData(new Data());
RequestCommonFPKJ beanData = new RequestCommonFPKJ();
COMMON_FPKJ_FPT commonFpkjFpt = new COMMON_FPKJ_FPT();
commonFpkjFpt.setFPQQLSH("whhy"+new Date().getTime()+000);
commonFpkjFpt.setKPLX("0");
commonFpkjFpt.setBMB_BBH("30.0");
commonFpkjFpt.setXSF_NSRSBH("15000119230104170217");
commonFpkjFpt.setXSF_MC("15000119230104170217");
commonFpkjFpt.setXSF_DZDH("18779190908");
commonFpkjFpt.setGMF_MC("购买方名称");
commonFpkjFpt.setKPR("开票人");
commonFpkjFpt.setJSHJ("20.40");
commonFpkjFpt.setHJJE("20.00");
commonFpkjFpt.setHJSE("0.40");
COMMON_FPKJ_XMXXS common_fpkj_xmxxs = new COMMON_FPKJ_XMXXS();
List<COMMON_FPKJ_XMXX> commonFpkjXmms = new ArrayList<>();
COMMON_FPKJ_XMXX commonFpkjXmxx = new COMMON_FPKJ_XMXX();
commonFpkjXmxx.setFPHXZ("0");
commonFpkjXmxx.setSPBM("2000000000000000000");
commonFpkjXmxx.setYHZCBS("0");
commonFpkjXmxx.setXMJE("20.00");
commonFpkjXmxx.setSL("0.02");
commonFpkjXmxx.setSE("0.04");
commonFpkjXmms.add(commonFpkjXmxx);
beanData.setCOMMON_FPKJ_FPT(commonFpkjFpt);
common_fpkj_xmxxs.setCommonFpkjXmxxs(commonFpkjXmms);
common_fpkj_xmxxs.setSize(commonFpkjXmms.size());
beanData.setCOMMON_FPKJ_XMXXS(common_fpkj_xmxxs);
Object obj = TicketUtil.test2(bean, beanData, env);
if(obj instanceof String){
return new ResultEntity(obj);
} else{
JSONObject jsonObject = (JSONObject)obj;
return new ResultEntity(jsonObject);
}
}
}