- 下载微信官方提供的SDK,转 https://blog.csdn.net/qq_40506288/article/details/110918650 博客查看下载流程
- 微信退款说明,官方提供:https://pay.weixin.qq.com/wiki/doc/api/external/jsapi.php?chapter=9_4
- 代码
这个类请转值:https://blog.csdn.net/qq_40506288/article/details/110918650 @Autowired private MyWxPayConfig myWxPayConfig; //申请退款 public String wechatBack() throws Exception{ Map<String, String> map = new HashMap<>(); map.put("appid", "appid"); map.put("mch_id", "mch_id"); map.put("transaction_id", "微信支付单号"); map.put("out_trade_no", "支付时候的订单号");//商户订单号 map.put("out_refund_no", "自定义的退款单号");//商户退款单号 map.put("total_fee", "订单金额"); map.put("refund_fee", "退款金额");//退款金额 map.put("refund_fee_type", "CNY");//币制,固定CNY,国内 map.put("notify_url", "回调通知URL"); //微信官方提供的SDK,下载可以之间调用,不需要写API WXPay wxpay = new WXPay(myWxPayConfig); //申请退款 Map<String, String> refundMap = wxpay.refund(map); String returnCode = refundMap.get("return_code"); String errCodeDes = refundMap.get("err_code_des"); String resultCode = refundMap.get("result_code"); if (returnCode.equals("SUCCESS") && resultCode.equals("SUCCESS")) { return "申请退款成功"; } else { return "申请退款失败"; } }
- 回调,退款成功后微信通知的地址,无参,微信回调说明:https://pay.weixin.qq.com/wiki/doc/api/external/jsapi.php?chapter=9_16&index=8
//获取微信退款通知的xml值
@RequestMapping(value = "/wechatRefund", method = RequestMethod.POST) public String wechatRefund(HttpServletRequest request, HttpServletResponse response) { try { InputStream is = request.getInputStream(); //将InputStream转换成String BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuilder sb = new StringBuilder(); String line = null; try { while ((line = reader.readLine()) != null) { sb.append(line + "\n"); } } catch (IOException e) { e.printStackTrace(); } finally { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } String resXml = sb.toString(); logger.info("微信退款异步通知请求包------"); logger.info(resXml); return wechatRefund(resXml); } catch (Exception e) { logger.error("微信退款回调通知失败", e); String result = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml> "; return result; } }
- 处理微信返回的报文
public String wechatRefund(String xmlStr) { String xmlBack = ""; Map<String, String> notifyMap = null; String lockKey = "refund_back_"; try { // 转换成map,微信官方提供的SDK notifyMap = WXPayUtil.xmlToMap(xmlStr); //解密 String reqInfo = decryptData(notifyMap.get("req_info")); //返回的数据 Map<String, String> map = WXPayUtil.xmlToMap(reqInfo);// 转换成map if (null == map || map.size() == 0) { logger.info("解密异常"); return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml>"; } //支付交易号 String transactionId = map.get("transaction_id"); //订单号sys/sysDepart/batchSyncSysDepart String outTradeNo = map.get("out_trade_no"); //退款交易号 String refundId = map.get("refund_id"); //退款单号 String outRefundNo = map.get("out_refund_no"); //订单金额 String totalFee = map.get("total_fee"); String settlementTotalFee = map.get("settlement_total_fee"); //申请金额 String refundFee = map.get("refund_fee"); //退款金额 String settlementRefundFee = map.get("settlement_refund_fee"); //退款状态 String refundStatus = map.get("refund_status"); //成功时间 String successTime = map.get("success_time"); String refundRecvAccout = map.get("refund_recv_accout"); String refundAccount = map.get("refund_account"); String refundRequestSource = map.get("refund_request_source"); if (null == settlementRefundFee) { logger.info("退款金额为空"); return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml>"; } if (null == outRefundNo) { logger.info("商户退款单号为空"); return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml>"; } if (null == refundId) { logger.info("微信退款单号为空"); return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml>"; } logger.info("\n\t----------------------------------------------------------\n\t" + "订单退款成功" + "\n\t----------------------------------------------------------"); return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>"; } catch (Exception e) { e.printStackTrace(); logger.info("退款回调失败"); return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml>"; } finally { LockHelper.remove(lockKey); } }
- 微信退款报文里面的req_info值需要解密,解密方法
public String decryptData(String decryptData) throws Exception { SecretKeySpec keySpec = new SecretKeySpec(MD5Util.MD5Encode("自己的密钥", "UTF-8").toLowerCase().getBytes(), "AES"); Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, keySpec); byte[] buffer = new BASE64Decoder().decodeBuffer(decryptData); return new String(cipher.doFinal(buffer), "UTF-8"); }