上一篇写了支付,这篇写个退款,网上的坑爹代码不是很全。当然我的也不全,不过重要代码都有了。
需要源码加QQ1137586868
注意事项,
1首先你要去商户后台申请一下退款的证书,证书必须得要(支付不用,退款用。)
2退款中必须传递你支付时的订单号或者微信给你返回成功的唯一标识。(微信要记录是你哪个订单退款的)
/**
* 申请退款
*
* @param payId 商户订单号 支付时的订单号
* @param refundId 商户退款单号 新生成
* @param money 是订单金额也是退款金额
*/
public static Map<String, String> refundmargin(String payId,String refundId,int money) {
System.out.println("----------开始微信退款-------");
//
SortedMap<String, String> params = new TreeMap<>();
params.put("appid", Constants.appID);
params.put("mch_id", Constants.MCH_ID);
params.put("nonce_str", PayUtil.createCode(32));
// //商户订单号和微信订单号二选一
params.put("out_trade_no", payId);
params.put("out_refund_no", refundId);
params.put("total_fee", String.valueOf(money*Constants.MOENY_PRPORTION));
params.put("refund_fee", String.valueOf(money*Constants.MOENY_PRPORTION));
//签名算法
String stringA = PayUtil.createLinkString(params);
//第二步,在stringA最后拼接上key得到stringSignTemp字符串,并对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,得到sign值signValue。(签名)
String sign = PayUtil.sign(stringA, Constants.key, "utf-8").toUpperCase();
params.put("sign", sign);
try {
String xml = PayUtil.GetMapToXML(params);
String xmlStr = doRefund("https://api.mch.weixin.qq.com/secapi/pay/refund", xml);
//加入微信支付日志
Map map = PayUtil.doXMLParse(xmlStr);
System.out.println("-----------返回的MAP数据----------"+map);
if (map == null || !"SUCCESS".equals(map.get("return_code"))) {
//消息通知
System.out.println("-----退款发起失败-----"+map);
return null;
}
//成功的话就在下面写自己的逻辑吧
return map;
} catch (Exception e) {
//微信退款接口异常
System.out.println("-------微信退款接口异常------");
}
return null;
}
/**
* 申请退款
*/
public static String doRefund(String url, String data) throws Exception {
StringBuilder sb = new StringBuilder();
try {
KeyStore keyStore = KeyStore.getInstance("PKCS12");
//证书放好哦,我这个是linux的路径,相信乖巧的你也肯定知道windows该怎么写
FileInputStream instream = new FileInputStream(new File("/usr/local/tomcat3/webapps/cert/apiclient_cert.p12"));
String mchid = Constants.MCH_ID;
try {
keyStore.load(instream, mchid.toCharArray());
} finally {
instream.close();
}
// 证书
SSLContext sslcontext = SSLContexts.custom()
.loadKeyMaterial(keyStore, mchid.toCharArray())
.build();
// 只允许TLSv1协议
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslcontext,
new String[]{"TLSv1"},
null,
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
//创建基于证书的httpClient,后面要用到
CloseableHttpClient client = HttpClients.custom()
.setSSLSocketFactory(sslsf)
.build();
HttpPost httpPost = new HttpPost(url);//退款接口
StringEntity reqEntity = new StringEntity(data);
// 设置类型
reqEntity.setContentType("application/x-www-form-urlencoded");
httpPost.setEntity(reqEntity);
CloseableHttpResponse response = client.execute(httpPost);
try {
HttpEntity entity = response.getEntity();
System.out.println(response.getStatusLine());
if (entity != null) {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent(), "UTF-8"));
String text = "";
while ((text = bufferedReader.readLine()) != null) {
sb.append(text);
}
}
EntityUtils.consume(entity);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return sb.toString();
}
这是下载证书的路径
看完有帮助就点个赞。