記錄本身爬過的坑。php
你們先感覺一下來自微信官方的申請退款API文檔帶來的魅力。。。java
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4git
下面是實現方法:api
先貼出主方法,其中用到的工具類和方法會在下面貼出來微信
/** * 微信退款 * @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; }
工具類和方法解釋:app
一、XmlToMap工具類dom
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; } }
二、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(); }
三、隨機字符串生成方法微信支付
/** * 隨機字符串 * @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; }
四、編寫簽名方法ui
/** * 編寫簽名 * @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; }
五、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" }; }
編寫時間倉促,代碼不足之處但願多多包涵並提出更改意見 937017870@qq.com
你們也能夠參考一下這裏,這裏寫的也比較詳細