微信退款接口

记录自己爬过的坑。

大家先感受一下来自微信官方的申请退款API文档带来的魅力。。。

https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4

下面是实现方法:

先贴出主方法,其中用到的工具类和方法会在下面贴出来

	/**
	 * 微信退款
	 * @throws Exception 
	 */
	public static String refundFunction(Map<String, Object> map) throws Exception {
        //这里的map主要有两个参数(商户号mchId和订单金额totalFee)
		String result = "";//这里用于返回处理返回结果 
		//xml转换为map,这里用于方便自己后面取出打印结果
		XmlToMap xmlToMap = new XmlToMap();
        //这里是自己封装的一些配置文件,大家可以跳过这一步,下面用到这里会和大家说明
		MyConfig config = null;
		try {
			//加载配置
			config = new MyConfig();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		//获取商户订单号和订单金额
		String mchId = map.get("mchId").toString();
		//获取订单金额(退款金额默认全部)
        //这里是自己做的一些格式的转换,有点笨拙,希望不影响大家的思路
		String a = map.get("totalFee")+"";
		String b = Double.valueOf(a) + "";
		int lastindex = b.indexOf(".");
		b = b.substring(0 , lastindex);
		int c = Integer.parseInt(b);
//		String d = c + "";
//		System.out.println("refundMoney--------->"+refundMoney);
		String totalFee = c  + "";
		//获取微信订单号
//		String transactionId = map.get("transactionId").toString();

		SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();  
	       parameters.put("appid", config.getAppID());//appid  
	       parameters.put("mch_id", config.getMchID());//商户号   
	       parameters.put("nonce_str", CreateNoncestr());//随机数  
//	       parameters.put("transaction_id", transactionId);//微信支付单号  
	       parameters.put("out_trade_no", mchId);//商户订单号  
	       parameters.put("out_refund_no", CreateNoncestr());//我们自己设定的退款申请号,约束为UK
	       parameters.put("total_fee", totalFee) ;//订单金额 单位为分!!!这里稍微注意一下  
	       parameters.put("refund_fee", totalFee);//退款金额 单位为分!!! 
	       parameters.put("op_user_id", config.getMchID());//操作人员,默认为商户账号
	       String sign = createSign("utf-8", parameters);  
	       System.out.println("sign---->"+sign);//签名
	       parameters.put("sign", sign);  
	       
           //xml和map之间的转换
	       String reuqestXml = getRequestXml(parameters);  
	       Map<String, Object> xmlMap = XmlToMap.xmlStr2Map(reuqestXml);
	       
	       KeyStore keyStore  = KeyStore.getInstance("PKCS12");  
	       FileInputStream instream = new FileInputStream(new File(config.certPath));//放退款证书的路径  
	       try {  
	    	   keyStore.load(instream, config.getMchID().toCharArray());//商户号  
	       } finally {  
	    	   instream.close();  
	       }  
	  
           //这里导包注意一下,可能会冲突
	       SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, config.getMchID().toCharArray()).build();//商户号  
	       SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(  
	              sslcontext,  
	              new String[] { "TLSv1" },  
	              null,  
	              SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);  
	       CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();  
	       try {  
	    	   HttpPost httpPost = new HttpPost(config.refund_url);//退款接口  
	            
	    	   System.out.println("executing request" + httpPost.getRequestLine());  
	    	   StringEntity  reqEntity  = new StringEntity(reuqestXml);  
	    	   // 设置类型  
	    	   reqEntity.setContentType("application/x-www-form-urlencoded");  
	    	   httpPost.setEntity(reqEntity);  
	    	   CloseableHttpResponse response = httpclient.execute(httpPost);  
	    	   try {  
	              HttpEntity entity = response.getEntity();  
	  
	              System.out.println("----------------------------------------");  
	              System.out.println(response.getStatusLine());  
	              if (entity != null) {  
	                  System.out.println("Response content length: " + entity.getContentLength());  
	                  BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent(),"UTF-8")); 
	                  System.out.println("bufferedReader.readLine()--->"+bufferedReader.readLine());
	                  String text;  
                      //这里是自己做的输出结果,方便查看错误原因
	                  while ((text = bufferedReader.readLine()) != null) {  
	                      System.out.println(text);
	                      if(!text.startsWith("</xml>")) {
	                    	  text = "<xml>"+text+"</xml>";
	                    	  Map<String, Object> xmlResultMap = XmlToMap.xmlStr2Map(text);
	                    	  if(xmlResultMap.get("result_code") != null) {
	                    		  result = xmlResultMap.get("result_code")+"";
	                    	  }
	                      }
	                  }  
	              }  
	              EntityUtils.consume(entity);  
	    	   } finally {  
	              response.close();  
	          }  
	      } finally {  
	          httpclient.close();  
	      }
		return result;  
	}

工具类和方法解释:

1、XmlToMap工具类

public class XmlToMap {

	//xml形式的字符串转换为map集合  
    public static Map<String,Object> xmlStr2Map(String xmlStr){  
        Map<String,Object> map = new HashMap<String,Object>();  
        Document doc;  
        try {  
            doc = DocumentHelper.parseText(xmlStr);  
            Element root = doc.getRootElement();    
            List children = root.elements();    
            if(children != null && children.size() > 0) {    
                for(int i = 0; i < children.size(); i++) {    
                    Element child = (Element)children.get(i);    
                    map.put(child.getName(), child.getTextTrim());    
                }    
            }    
        } catch (DocumentException e) {  
            e.printStackTrace();  
        }  
        return map;  
    } 
	
}

2、getRequestXml方法

   /**
      * 转为xml格式
      * @param parameters
      * @return
      */
     public static String getRequestXml(SortedMap<Object,Object> parameters){  
         StringBuffer sb = new StringBuffer();  
         sb.append("<xml>");  
         Set es = parameters.entrySet();  
         Iterator it = es.iterator();  
         while(it.hasNext()) {  
           Map.Entry entry = (Map.Entry)it.next();  
           String k = (String)entry.getKey();  
           String v = (String)entry.getValue();  
           if ("attach".equalsIgnoreCase(k)||"body".equalsIgnoreCase(k)||"sign".equalsIgnoreCase(k)) {  
               sb.append("<"+k+">"+"<![CDATA["+v+"]]></"+k+">");  
           }else {  
               sb.append("<"+k+">"+v+"</"+k+">");  
           }  
         }  
         sb.append("</xml>");  
         return sb.toString();  
     }  
     

3、随机字符串生成方法

	/**
	 * 随机字符串
	 * @return
	 */
    public static String CreateNoncestr() {  
        String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";  
        String res = "";  
        for (int i = 0; i < 16; i++) {  
            Random rd = new Random();  
            res += chars.charAt(rd.nextInt(chars.length() - 1));  
        }  
        return res;  
     }  

4、编写签名方法

/**
     * 编写签名
     * @param charSet
     * @param parameters
     * @return
     * @throws Exception 
     */
     public static String createSign(String charSet,SortedMap<Object,Object> parameters) throws Exception{  
    	MyConfig myconfig = new MyConfig();
        StringBuffer sb = new StringBuffer();  
        Set es = parameters.entrySet();  
        Iterator it = es.iterator();  
        while(it.hasNext()) {  
            Map.Entry entry = (Map.Entry)it.next();  
            String k = (String)entry.getKey();  
            Object v = entry.getValue();  
            if(null != v && !"".equals(v)  
                    && !"sign".equals(k) && !"key".equals(k)) {  
                sb.append(k + "=" + v + "&");  
            }  
        }  
        sb.append("key=" + myconfig.getKey());  
//        String sign = MD5Util.MD5Encode(sb.toString(), charSet).toUpperCase();  
        String sign = MD5Util.MD5Encode(sb.toString(), charSet).toUpperCase();  
//        String sign = MD5.MD5Encode(sb.toString(), charSet).toUpperCase();  
        return sign;  
      }  

5、MD5Util工具类

import java.security.MessageDigest;

public class MD5Util {

	private static String byteArrayToHexString(byte b[]) {
		StringBuffer resultSb = new StringBuffer();
		for (int i = 0; i < b.length; i++)
			resultSb.append(byteToHexString(b[i]));

		return resultSb.toString();
	}

	private static String byteToHexString(byte b) {
		int n = b;
		if (n < 0)
			n += 256;
		int d1 = n / 16;
		int d2 = n % 16;
		return hexDigits[d1] + hexDigits[d2];
	}

	public static String MD5Encode(String origin, String charsetname) {
		String resultString = null;
		try {
			resultString = new String(origin);
			MessageDigest md = MessageDigest.getInstance("MD5");
			if (charsetname == null || "".equals(charsetname))
				resultString = byteArrayToHexString(md.digest(resultString
						.getBytes()));
			else
				resultString = byteArrayToHexString(md.digest(resultString
						.getBytes(charsetname)));
		} catch (Exception exception) {
		}
		return resultString;
	}

	private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5",
		"6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
}

编写时间仓促,代码不足之处希望多多包涵并提出更改意见  [email protected]

大家也可以参考一下这里,这里写的也比较详细

http://blog.csdn.net/xiaozhegaa/article/details/79180117

猜你喜欢

转载自my.oschina.net/u/3723429/blog/1616766