版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cl11992/article/details/86712009
一、介绍
本文介绍了微信申请退款的代码实例,如有不足的请提出,我会做出改正。
二、官方文档
申请退款:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_4
三、微信SDK安装方法
微信PC扫码支付(一)-maven本地仓库安装:微信支付sdk
四、申请退款
注意:申请退款需要商家证书,需提前下载
- 下文PayException为自定义异常类
- 下文WeixinConfig为微信需要固定参数类
调用申请退款
public Object refund(Map<String, Object> map) throws PayException {
Map<String,String> resultMap=new HashMap<>();
try {
if(map.isEmpty()){
logger.error("微信申请退款缺少参数");
throw new PayException("微信申请退款缺少参数");
}
//随机字符串
String nonceStr=Long.toString(System.currentTimeMillis() / 1000);
logger.info("微信退款-nonce_str:"+nonceStr);
//商户订单号
String outTradeNo = (String)map.get("outTradeNo");
logger.info("微信退款-商户订单号out_trade_no:"+outTradeNo);
//退款单号
String outRefundNo = (String)map.get("outRefundNo");
logger.info("微信退款-退款单号out_refund_no:"+outRefundNo);
//订单总金额
String totalFee = map.get("amountPaid").toString();
logger.info("微信退款-订单总金额total_fee:"+totalFee);
//退款总金额
String refundFee = map.get("refundFee").toString();
logger.info("微信退款-退款金额refund_fee:"+refundFee);
//验证参数
if(StringUtils.isBlank(outTradeNo)){
logger.error("微信申请退款缺少参数-商户订单号为空");
throw new PayException("微信申请退款缺少参数-商户订单号不能为空");
}
if(StringUtils.isBlank(outRefundNo)){
logger.error("微信申请退款缺少参数-退款单号为空");
throw new PayException("微信申请退款缺少参数-退款单号不能为空");
}
if(StringUtils.isBlank(totalFee)){
logger.error("微信申请退款缺少参数-订单总金额为空");
throw new PayException("微信申请退款缺少参数-订单总金额不能为空");
}
if(StringUtils.isBlank(refundFee)){
logger.error("微信申请退款缺少参数-退款总金额为空");
throw new PayException("微信申请退款缺少参数-退款总金额不能为空");
}
Map<String, String> packageParams = new HashMap<String, String>();
WeixinConfig weixinConfig=new WeixinConfig();
int price1 = (int)(Float.valueOf(totalFee)*100);//总钱数
int price2 = (int)(Float.valueOf(refundFee)*100);//退款钱数
packageParams.put("appid", weixinConfig.getAppID());
packageParams.put("mch_id", weixinConfig.getMchID());
packageParams.put("nonce_str", nonceStr);
packageParams.put("notify_url", weixinConfig.getNotifyUrl());
packageParams.put("out_trade_no",outTradeNo);
packageParams.put("out_refund_no",outRefundNo);
packageParams.put("total_fee", Integer.toString(price1));
packageParams.put("refund_fee", Integer.toString(price2));
//签名
String sign=WXPayUtil.generateSignature(packageParams, weixinConfig.getKey());
packageParams.put("sign",sign);
logger.info("微信申请退款-sign:"+sign);
//拼接需要提交微信的数据
String xml = WXPayUtil.mapToXml(packageParams);
String result = null;
try {
result = ClientCustomSSL.doRefund(xml);
if(StringUtils.isBlank(result)){
logger.error("微信申请退款发生错误");
throw new PayException("微信申请退款发生错误");
}
Map<String, String> refundResultMap = WXPayUtil.xmlToMap(result);
String returnCode = (String) refundResultMap.get("return_code");
logger.info("微信申请退款-return_code:"+returnCode);
if(!returnCode.equals("SUCCESS")){
String returnMsg = (String) refundResultMap.get("return_msg");
if(StringUtils.isBlank(returnMsg)){
returnMsg = "微信申请退款发生错误";
}
logger.info("微信申请退款-return_msg:"+returnMsg);
resultMap.put("returnCode","FAIL");
resultMap.put("returnMsg", returnMsg);
return resultMap;
}
String resultCode = (String)refundResultMap.get("result_code");
if(!resultCode.equals("SUCCESS")){
String errCodeDes = (String) refundResultMap.get("err_code_des");
if(StringUtils.isBlank(errCodeDes)){
errCodeDes = "微信申请退款发生错误";
}
logger.info("微信申请退款-err_code_des:"+errCodeDes);
resultMap.put("returnCode","FAIL");
resultMap.put("returnMsg", errCodeDes);
return resultMap;
}
resultMap.put("returnCode", "SUCCESS");
resultMap.put("returnMsg", "微信申请退款成功");
logger.info("微信退款申请成功");
return resultMap;
} catch (PayException e) {
logger.error("微信申请退款发生错误:",e);
throw new PayException("微信申请退款发生错误");
}
} catch (Exception e) {
logger.error("微信申请退款发生错误:",e);
throw new PayException("微信申请退款发生错误");
}
}
ClientCustomSSL.java
public class ClientCustomSSL {
/*
* 使用商户证书去退款
*/
public static String doRefund(String data) throws Exception {
WeixinConfig weixinConfig=new WeixinConfig();
String payCert = "XXXXXXXXXX";//商户证书地址
KeyStore keyStore = KeyStore.getInstance("PKCS12");
FileInputStream is = new FileInputStream(payCert);
try {
keyStore.load(is, weixinConfig.getMchID().toCharArray());// 这里写密码..默认是你的MCHID(商户号)
} finally {
is.close();
}
SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, weixinConfig.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 httpost = new HttpPost("https://api.mch.weixin.qq.com/secapi/pay/refund"); // 设置响应头信息
httpost.addHeader("Connection", "keep-alive");
httpost.addHeader("Accept", "*/*");
httpost.addHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");
httpost.addHeader("Host", "api.mch.weixin.qq.com");
httpost.addHeader("X-Requested-With", "XMLHttpRequest");
httpost.addHeader("Cache-Control", "max-age=0");
httpost.addHeader("User-Agent","Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
httpost.setEntity(new StringEntity(data, "UTF-8"));
CloseableHttpResponse response = httpclient.execute(httpost);
try {
HttpEntity entity = response.getEntity();
String jsonStr = EntityUtils.toString(response.getEntity(),"UTF-8");
EntityUtils.consume(entity);
return jsonStr;
} finally {
response.close();
}
} finally {
httpclient.close();
}
}
}