微信退款
public class RefundRequest { @ApiModelProperty(value = "用户id") @JsonProperty(value = "user_id") private Integer userId; @ApiModelProperty(value = "支付订单交易号") @JsonProperty(value = "trade_no") private String tradeNo; @ApiModelProperty(value = "退款金额(/分)") private Integer amount; @ApiModelProperty(value = "退款原因") private String reason; @ApiModelProperty(value = "自定义信息") private Map<String, Object> optional; @ApiModelProperty(value = "产品标识") @JsonProperty(value = "product_key") private String productKey; @ApiModelProperty(value = "行为标识") private String attribute; @ApiModelProperty(value = "退款单号") private String refundNo; }
微信退款
public String refundWX(RefundRequest refundRequest) { String refundNo = generateBillNoService.randomRefundNo(12); String appId=""; String mchid=""; String appKey=""; //微信退款 SortedMap<String, Object> sortedMapmap = new TreeMap<>(); sortedMapmap.put("appid", appId); sortedMapmap.put("mch_id", mchid); sortedMapmap.put("nonce_str", generateBillNoService.generateRandomString(12)); sortedMapmap.put("out_trade_no", refundRequest.getTradeNo()); sortedMapmap.put("total_fee", refundRequest.getAmount().toString()); sortedMapmap.put("refund_fee", refundRequest.getAmount().toString()); sortedMapmap.put("out_refund_no", refundNo); sortedMapmap.put("notify_url", "回调地址"); String sign = weiXinProxy.createSign("UTF-8", sortedMapmap, appKey); sortedMapmap.put("sign", sign); Map<String, String> map = weiXinProxy.refundOrdes(Constant.WX_REFUND_URL, sortedMapmap, mchid); log.info("申请退款结果:" + map); //校验(方法在上个文章里) DefaultResponse defaultResponse = weiXinProxy.checkResultInfo(map, appKey); if (defaultResponse.getCode() != 0) { log.info(defaultResponse.getMessage()); return "FAIL"; } return "SUCCESS"; }
调用微信 证书验证
public Map<String, String> refundOrdes(@RequestBody String url, SortedMap<String, Object> request, String muchid) { Map<String, String> map = new HashMap<>(); try { RestTemplate restTemplate = new RestTemplate(certificateVerification(muchid)); log.info("证书验证成功"); map = doXMLParse(new String(restTemplate.postForObject(url, getRequestXml(request), String.class).getBytes("ISO-8859-1"), "UTF-8")); } catch (Exception e) { e.printStackTrace(); log.info("证书验证失败"); } return map; } //验证证书 public HttpComponentsClientHttpRequestFactory certificateVerification(String muchid) throws Exception { //PKCS12证书 是从微信商户平台-账户设置-API安全 中下载的 KeyStore keyStore = KeyStore.getInstance("PKCS12"); //指向你的证书的路径 InputStream inputStream = this.getClass().getResourceAsStream("/apiclient_cert.p12"); try { //默认密码MCHID keyStore.load(inputStream, muchid.toCharArray()); } finally { inputStream.close(); } //SSL通信双向认证 SSLContext sslContext = SSLContexts.custom().loadKeyMaterial(keyStore, muchid.toCharArray()).build(); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new String[]{"TLSv1"}, null, NoopHostnameVerifier.INSTANCE); CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build(); return new HttpComponentsClientHttpRequestFactory(httpClient); }
退款结果回调
//微信退款通知 public String callBackWXRefund(String xml) { Map<String, String> map = new HashMap<>(); try { if (xml == null) return "FAIL"; map = weiXinProxy.doXMLParse(xml); log.info(map); if (map.get("return_code").equals("SUCCESS")) { //base64解码 byte[] decodeReqInfo = Base64.decode(map.get("req_info")); log.info(decodeReqInfo); String appKey =""; //对商户key做md5,得到32位小写key String md5Key = weiXinProxy.MD5Encode(appKey, "UTF-8").toLowerCase(); //PKCS7Padding填充 AES-256-ECB解密 注意:jdk版本低 会报Illegal key size or default parameters Security.addProvider(new BouncyCastleProvider()); Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC"); cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(md5Key.getBytes(), "AES")); String reqInfo = new String(cipher.doFinal(decodeReqInfo),"utf-8"); log.info(reqInfo); Map<String, String> reqInfoMap = weiXinProxy.doXMLParse(reqInfo); log.info("退款结果回调:" + reqInfoMap); } return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>"; } catch (Exception e) { log.info(e.getMessage()); } return "FAIL"; } }