* @param request
* @param response
* @param appId
* @param secret
* @param shh
* @param key
* @param orderId
* @param total_fee
* @param refund_fee
* @param path
* @return
*/
public static Object wxRefund(HttpServletRequest request,HttpServletResponse response,String appId,
String secret,String shh,String key,String orderId,String total_fee,String refund_fee,String path){
Map<String,String> result=new HashMap<String,String>();
String refundid = "";
String nonce_str = String.valueOf(new Random().nextInt(10000));
/*----- 1.生成预支付订单需要的的package数据-----*/
SortedMap<String, Object> packageParams = new TreeMap<String, Object>();
packageParams.put("appid", APP_ID);
packageParams.put("mch_id", MCH_ID);
packageParams.put("nonce_str", nonce_str);
packageParams.put("op_user_id", shh);
packageParams.put("out_trade_no", orderId);
packageParams.put("out_refund_no", orderId);
packageParams.put("total_fee",1);
packageParams.put("refund_fee", 1);
/*----2.根据package生成签名sign---- */
String sign=createSign("UTF-8", packageParams);
packageParams.put("sign", sign);
/*----3.拼装需要提交到微信的数据xml---- */
String xml=getRequestParamToXML(packageParams);
try {
/*----4.读取证书文件,这一段是直接从微信支付平台提供的demo中copy的,所以一般不需要修改---- */
KeyStore keyStore = KeyStore.getInstance("PKCS12");
FileInputStream instream = new FileInputStream(new File(path));
try {
keyStore.load(instream, shh.toCharArray());
} finally {
// instream.close();
}
// Trust own CA and all self-signed certs
SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, shh.toCharArray()).build();
// Allow TLSv1 protocol only
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext,new String[] { "TLSv1" },null,
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
/*----5.发送数据到微信的退款接口---- */
String url="https://api.mch.weixin.qq.com/secapi/pay/refund";
HttpPost httpost= new HttpPost(url);
httpost.setEntity(new StringEntity(xml, "UTF-8"));
HttpResponse weixinResponse = httpClient.execute(httpost);
String jsonStr = EntityUtils.toString(weixinResponse.getEntity(), "UTF-8");
logger.info(jsonStr);
Map map = doXMLParse(jsonStr);
if("success".equalsIgnoreCase((String) map.get("return_code"))){
logger.info("退款成功");
result.put("refund_id", map.get("refund_id").toString());
result.put("returncode", "ok");
result.put("returninfo", "退款成功");
}else{
logger.info("退款失败");
result.put("returncode", "error");
result.put("returninfo", "退款失败");
}
} catch (Exception e) {
logger.info("退款失败");
result.put("returncode", "error");
result.put("returninfo", "退款失败");
}
return result;
}
/**
*微信公众号申请退款
* @param orderId 订单id
* @param total_fee 退款金额
* @param refund_fee 退款金额
* @param response
* @return
* @throws Exception
*/
@SuppressWarnings("unused")
public static Map<String, String> refundwx(HttpServletRequest request,HttpServletResponse response,OrdSale ordSale){
/*--------1.初始化数据参数----------*/
String appId= APP_ID;
String secret= APP_SECRET;
String shh= MCH_ID;
String key= API_KEY;
String filePath = ServletActionContext.getServletContext().getRealPath(
"diplomafile" + System.getProperty("file.separator")
+ "apiclient_cert.p12"); //退款需要提供证书数据,所以需要根据证书路径读取证书
//需要退款的商户订单号,对应提交订单中的out_trade_no
String orderId = ordSale.getCode();
String total_fee="1"; //也可以根据业务场景从数据库中获取总金额和退款金额
String refund_fee="1";
Map<String,String> result = (Map<String, String>) wxRefund(request,response,appId,secret,shh,key,orderId,total_fee,refund_fee,filePath);
return result;
}
/**将请求参数转换成XML
* @param params
* @return
*/
private static String getRequestParamToXML(SortedMap<String, Object> params){
StringBuilder reqXml=new StringBuilder();
reqXml.append("<xml>");
for(Map.Entry<String, Object> entry:params.entrySet()){
if("sign".equalsIgnoreCase(entry.getKey())){
sign="<sign>"+entry.getValue()+"</sign>";
}else{
reqXml.append("<"+entry.getKey()+">").append(entry.getValue()).append("</"+entry.getKey()+">");
}
}
reqXml.append(sign);
//reqXml.append("<key>"+API_KEY+"</key>");
reqXml.append("</xml>");
return reqXml.toString();
}
/**
* 生成签名
* @param charEncode
* @param params
* @return
*/
public static String createSign(String charEncode,SortedMap<String, Object> params){
StringBuilder sb=new StringBuilder();
for(Map.Entry<String, Object> entry:params.entrySet()){
if(entry.getValue()!=null&&!"".equals(entry.getValue())
&&!"sign".equals(entry.getKey())&&!"key".equals(entry.getKey())){
sb.append(entry.getKey()+"="+entry.getValue()+"&");
}
}
sb.append("key="+API_KEY);
String sign=MD5.getMD5Encode(sb.toString(), charEncode).toUpperCase();
return sign;
}