1. 程式人生 > >rest介面訪問webService soap介面 用XStream javabean和xml的互轉

rest介面訪問webService soap介面 用XStream javabean和xml的互轉

建立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);
        }
    }

}