zoukankan      html  css  js  c++  java
  • 自定义XStream -Converter解析微信支付结果

    上周开发微信代扣,微信代扣结果通知的平面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);
    }
    
    
  • 相关阅读:
    内存泄漏检测工具
    RGB 颜色 代码 转换器
    索引 扫描及查找 1
    IIS7中Integrated和classic的区别
    HTTP请求上下文之终结:HttpContext类
    vs2010 快捷键大全
    IIS 7.0 中的 HTTP 状态代码
    JSON Date Format
    如何使用 MasterPage(注意母板页和子页面的执行顺序)
    B树、B树、B+树、B*树
  • 原文地址:https://www.cnblogs.com/hhbk/p/8377254.html
Copyright © 2011-2022 走看看