上周开发微信代扣,微信代扣结果通知的平面XML非常复杂,
对于子节点,需要使用者实现ComplexConvert接口进行解析...
* 总代金券退款金额 coupon_refund_fee_$n 否 Int 100 代金券退款金额<=退款金额,退款金额-代金券或立减优惠退款金额为现金,说明详见代金券或立减优惠
* 退款代金券使用数量 coupon_refund_count_$n 否 Int 1 退款代金券使用数量 ,$n为下标,从0开始编号
* 退款代金券ID coupon_refund_id_$n_$m 否 String(20) 10000 退款代金券ID, $n为下标,$m为下标,从0开始编号
* 单个代金券退款金额 coupon_refund_fee_$n_$m 否 Int 100 单个退款代金券支付金额, $n为下标,$m为下标,从0开始编号
* @see <a herf="https://pay.weixin.qq.com/wiki/doc/api/pap.php?chapter=18_7&index=8">微信支付结果通知</a>
public class WeixinHttpExecutor implements HttpExecutor {
private static final Logger LOG= LoggerFactory.getLogger(WeixinHttpExecutor.class);
@Resource(name = "httpClient")
HttpClient httpClient;
private static Map<Class,XStream> xStreamMap =new ConcurrentHashMap<Class,XStream>();
@Override
public <ExecuteResult extends Object> ExecuteResult post(Object parameter, String url, Class returnClass) {
XStream requestXStream=getXStream(parameter.getClass());
String xml=requestXStream.toXML(parameter);
HttpPost httpPost=new HttpPost(url);
httpPost.setEntity(new StringEntity(xml,"UTF-8"));
HttpResponse response=null;
try{
response= httpClient.execute(httpPost);
String responseXml= EntityUtils.toString(response.getEntity(),"UTF-8");
XStream returnStream=getXStream(returnClass);
return (ExecuteResult)returnStream.fromXML(responseXml);
}catch (Throwable throwable){
LOG.error(url);
LOG.error(GsonUtils.defaultGson().toJson(parameter));
LOG.error(throwable.getMessage(),throwable);
throw new RuntimeException(throwable);
}
finally {
if(null!=response&&null!=response.getEntity()) {
EntityUtils.consumeQuietly(response.getEntity());
}
}
}
private final XStream getXStream(Class clazz){
XStream stream=xStreamMap.get(clazz);
if(null==stream){
synchronized (WeixinHttpExecutor.class) {
if(null==stream) {
stream= NoNameCoderWithCDataFacotry.Instance().createWithRootXml(clazz);
if(clazz.getInterfaces().length>0){
for (Class c:clazz.getInterfaces()) {
if(c.equals(Converter.class)){
try {
stream.registerConverter((Converter) clazz.newInstance());
}catch (Throwable thrower){
LOG.error(thrower.getMessage(),thrower);
throw new RuntimeException(thrower);
}
}
}
}
xStreamMap.put(clazz,stream);
}
}
}
return stream;
}
}
public class WxPayCompletedResult extends BaseWeixinResult implements WeixinReturnParameter,ComplexConverter {
@Override
public void unmarshal(Map<String, String> xmlNodeValue) {
if(this.couponCount>0) {
couponPays = new ArrayList<>(this.couponCount);
for (int index=0;index<this.couponCount;++index){
CouponPay pay=new CouponPay();
pay.couponId=xmlNodeValue.get("coupon_id_"+String.valueOf(index));
pay.couponFee=Integer.valueOf(xmlNodeValue.get("coupon_fee_"+String.valueOf(index)));
couponPays.add(index,pay);
}
}
}
private List<CouponPay> couponPays;
private static Map<String,Field> FIELD_LIST=new HashMap<>();
static {
XStreamUtils.loadFields(FIELD_LIST,WxPayCompletedResult.class);
}
@Override
public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
}
@Override
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
try {
WxPayCompletedResult result = new WxPayCompletedResult();
Map<String, String> itemsMap = new HashMap<>();
if (reader.getNodeName().equalsIgnoreCase("xml")) {
while (reader.hasMoreChildren()) {
reader.moveDown();
String nodeName = reader.getNodeName().trim();
Field field;
if (FIELD_LIST.containsKey(nodeName)) {
field = FIELD_LIST.get(nodeName);
if (field.getType().equals(String.class)) {
field.set(result, reader.getValue());
} else if (field.getType().equals(int.class)||field.getType().equals(Integer.class)) {
field.set(result, Integer.valueOf(reader.getValue()).intValue());
}
}
itemsMap.put(nodeName, reader.getValue());
reader.moveUp();
}
}
result.unmarshal(Collections.unmodifiableMap(itemsMap));
return result;
}catch (Throwable throwable){
throw new RuntimeException(throwable);
}
}
@Override
public boolean canConvert(Class type) {
return type.equals(WxPayCompletedResult.class);
}
}
/**
* 复杂XML解析接口,实现者可以从映射中查找相应的VALUE,并自行构建复杂对象..
* 以适应微信支付结果复杂对象,形如下面例子...
* @see <a herf="https://pay.weixin.qq.com/wiki/doc/api/pap.php?chapter=18_10&index=11">微信代扣订单查询</a>
* Created by wangtingwei on 2018/1/25.
*/
public interface ComplexConverter extends Converter{
void unmarshal(Map<String,String> xmlNodeValue);
}