我們的微信支付,使用的是第三方的支付,某銀行的微信支持渠道。所有的接口請求、應答都是xml格式報文,這樣就需要用到xml格式報文的拼裝和解析,這兒簡單講一下。
拼接xml格式報文。
從頁面表單提交和配置文件中讀取出參數,或用實體類接收的頁面傳來的參數。建立map對象,用put()方法把參數添加進去。然后遍歷map,將map轉換成xml。
-
StringBuffer soapResultData =
new StringBuffer();
-
//xml聲明
-
soapResultData.append(
"<?xml version=\"1.0\" encoding=\"GBK\"?><ROOT><MSG_HEAD>");
-
//請求頭
-
soapResultData.append(requesttoxml(msgHead));
-
soapResultData.append(
"</MSG_HEAD><MSG_BODY>");
-
//請求體
-
soapResultData.append(requesttoxml(resmap));
-
soapResultData.append(
"</MSG_BODY></ROOT>");
-
/**
-
* 將map轉化為XML格式的字符串
-
* @param resmap
-
* @return
-
*/
-
public static String requesttoxml(Map<String, String> resmap){
-
StringBuffer soapResultData =
new StringBuffer();
-
for(String key : resmap.keySet()){
-
soapResultData.append(
"<");
-
soapResultData.append(key);
-
soapResultData.append(
">");
-
soapResultData.append(resmap.get(key));
-
soapResultData.append(
"</");
-
soapResultData.append(key);
-
soapResultData.append(
">");
-
}
-
return soapResultData.toString();
-
}
將接收到的xml格式報文,轉換成實體類。
-
package com.ustcsoft.business.model;
-
-
import java.io.Serializable;
-
-
import org.apache.commons.digester3.annotations.rules.BeanPropertySetter;
-
import org.apache.commons.digester3.annotations.rules.ObjectCreate;
-
-
@ObjectCreate(pattern =
"ROOT/MSG_HEAD")
-
public
class ResponseMsgHead implements Serializable {
-
/**
-
*
-
*/
-
private
static
final
long serialVersionUID = -
2793215313546940251L;
-
@BeanPropertySetter(pattern =
"ROOT/MSG_HEAD/TRAN_CODE")
-
private String TRAN_CODE;
-
@BeanPropertySetter(pattern =
"ROOT/MSG_HEAD/PARTNER_CODE")
-
private String PARTNER_CODE;
-
@BeanPropertySetter(pattern =
"ROOT/MSG_HEAD/REQUEST_SERIAL")
-
private String REQUEST_SERIAL;
-
@BeanPropertySetter(pattern =
"ROOT/MSG_HEAD/RESPONSE_DATE")
-
private String RESPONSE_DATE;
-
@BeanPropertySetter(pattern =
"ROOT/MSG_HEAD/RESPONSE_TIMESTAMP")
-
private String RESPONSE_TIMESTAMP;
-
@BeanPropertySetter(pattern =
"ROOT/MSG_HEAD/RESULT_CODE")
-
private String RESULT_CODE;
-
@BeanPropertySetter(pattern =
"ROOT/MSG_HEAD/RESULT_MESSAGE")
-
private String RESULT_MESSAGE;
-
//get set 省略,不貼在這兒,自己使用時別忘了生成個set和get方法
-
}
-
import
static org.apache.commons.digester3.binder.DigesterLoader.newLoader;
-
-
import java.io.StringReader;
-
import java.text.SimpleDateFormat;
-
import java.util.HashMap;
-
import java.util.Map;
-
import java.util.TreeMap;
-
-
import org.apache.commons.digester3.Digester;
-
import org.apache.commons.digester3.annotations.FromAnnotationsRuleModule;
-
import org.apache.log4j.Logger;
-
-
import com.ustcsoft.business.model.CreditPayResponseBody;;
-
import com.ustcsoft.business.model.ResponseMsgHead;
-
import com.ustcsoft.framework.util.HTTPUtil;
-
import com.ustcsoft.framework.util.XMlUtil;
-
-
public
class PayService {
-
private
final Map<Class<?>, FromAnnotationsRuleModule> xmlAnnotationModule =
new HashMap<Class<?>, FromAnnotationsRuleModule>();
-
private
static
final Logger logger=Logger.getLogger(PayService.class);
-
-
public PayService() {
-
xmlAnnotationModule.put(ResponseMsgHead.class,
-
new FromAnnotationsRuleModule() {
-
@Override
-
protected void configureRules() {
-
bindRulesFrom(ResponseMsgHead.class);
-
}
-
});
-
xmlAnnotationModule.put(CreditPayResponseBody.class,
-
new FromAnnotationsRuleModule() {
-
@Override
-
protected void configureRules() {
-
bindRulesFrom(CreditPayResponseBody.class);
-
}
-
});
-
}
-
-
//中間業務代碼省略……
-
-
public <T>
T parseXml(String xml, Class<T> clazz) throws Exception {
-
StringReader sr =
null;
-
try {
-
Digester digester = newLoader(xmlAnnotationModule.get(clazz)).newDigester();
-
sr =
new StringReader(xml);
-
T pi = digester.parse(sr);
-
digester.clear();
-
return pi;
-
}
finally {
-
if (sr !=
null) {
-
sr.close();
-
}
-
}
-
}
-
}
-
logger.info(
"統一下單接口請求報文:"+requestxml);
-
String resultxml = HTTPUtil.postByHttps(url, requestxml,
"GBK");
-
logger.info(
"統一下單接口返回報文:"+resultxml);
-
if(resultxml !=
null){
-
resultxml = XMlUtil.xmltoUpperCase(resultxml);
//
將XML報文中的標簽,全部轉化為大寫
-
ResponseMsgHead head = parseXml(resultxml, ResponseMsgHead.class);
-
CreditPayResponseBody body = parseXml(resultxml, CreditPayResponseBody.class);
-
if (
null != head) {
-
if(head.getRESULT_CODE().equals(
"000000")){
-
logger.info(
"下單成功");
-
logger.info(
"返回參數:sub_mch_id="+body.getSUB_MCH_ID()+
",total_fee="+body.getTOTAL_FEE()+
",out_trade_no="+body.getOUT_TRADE_NO());
-
return body;
-
}
else{
-
logger.info(
"下單失敗,錯誤碼:"+head.getRESULT_CODE()+
",錯誤信息:"+head.getRESULT_MESSAGE());
-
}
-
}
-
}
-
/**
-
* 將XML報文中的標簽,全部轉化為大寫
-
* @param xmlMessage
-
* @return
-
*/
-
public static String xmltoUpperCase(String xmlMessage) {
-
Pattern pattern = Pattern.compile(
"<.+?>");
-
String xml = xmlMessage.split(
">")[
0];
-
String xml0 = xmlMessage.substring(
0, xml.length()+
1);
-
String xml1 = xmlMessage.substring(xml.length()+
1);
-
StringBuilder res =
new StringBuilder();
-
int lastIdx =
0;
-
Matcher matchr = pattern.matcher(xml1);
-
while (matchr.find()) {
-
String str = matchr.group();
-
res.append(xml1.substring(lastIdx, matchr.start()));
-
res.append(str.toUpperCase());
-
lastIdx = matchr.end();
-
}
-
res.append(xml1.substring(lastIdx));
-
String result = xml0 + res.toString();
-
return result;
-
}
以上就是拼接xml格式報文和解析xml格式報文。需要注意的是,在解析xml格式報文時,由於對方返回的報文的標簽有小寫的,結果解析出錯,所以在里面做了個處理,將標簽全部轉化為大寫。