记录本身爬过的坑。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
你们也能够参考一下这里,这里写的也比较详细