微信退款功能实现
最近做了一个微信退款的功能,遇到了一些坑。网上也找了很多资料,但是发现大多都是微信支付这一块的东西,关于微信退款的很少,所以自己来写一份记录一下。好了,话不多说,我们直接进入主题:
相信大家都看微信支付的官方文档了,微信退款和其他的API接口不一样,它需要认证证书
。
我们需要去微信商户平台下载证书,怎么下载我这里就不做叙述了。直接给大家看一下下载之后的文件。
下载文件之后,我们就需要携带证书发送HTTPS请求微信的API接口了,直接上代码了。
1.把下载好的证书文件放进项目中,或者你的服务器上。我这里是放在项目里的resource文件夹下面。
2.代码中绑定此证书。
private static CloseableHttpClient noSslHttpClient(String mchId) throws KeyManagementException,
NoSuchAlgorithmException, KeyStoreException, CertificateException, IOException, UnrecoverableKeyException {
KeyStore keyStore = KeyStore.getInstance("PKCS12");
ClassPathResource resource = new ClassPathResource("crt/apiclient_cert.p12");
// 如果你的文件是放在服务器上面可以使用下面的方法
// 直接写你的服务器文件路径就可以,可能需要注意你服务器文件的访问权限,以避免读取不到文件
// FileInputStream stream = IoUtil.toStream(new File("/home/crt/apiclient_cert.p12"));
// keyStore.load(stream, mchId.toCharArray());
// 这里的证书密码默认为微信分配的 商户号
keyStore.load(resource.getInputStream(), mchId.toCharArray());
// 这里需要注意的一点是,这里调用的loadKeyMaterial方法依旧是传入密码的那个方法,密码还是微信分配的 商户号
final SSLContext sslContext = new SSLContextBuilder().loadKeyMaterial(keyStore, mchId.toCharArray()).build();
// 这里就算是返回一个已经绑定好正式的CloseableHttpClient对象了
return HttpClientBuilder.create().setSSLContext(sslContext)
.setConnectionManager(new PoolingHttpClientConnectionManager(RegistryBuilder
.<ConnectionSocketFactory>create().register("http", PlainConnectionSocketFactory.INSTANCE)
.register("https", new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE))
.build()))
.build();
}
3.请求微信退款API
Executor executor = null;
try {
// 这里调用上面的方法:noSslHttpClient
executor = Executor.newInstance(noSslHttpClient(wxMchId));
} catch (CertificateException | UnrecoverableKeyException e1) {
e1.printStackTrace();
logger.info("微信证书异常");
return ResponseData.fail("微信支付退款申请失败");
}
// 这里是请求对象,就是微信退款API需要的一些参数,请求的格式等,我这里就不做叙述了。微信文档中描述的很清楚
Request request = Request.Post(wxRefundUrl).addHeader("Content-Type", ContentType.APPLICATION_XML.getMimeType())
.bodyString(XMLUtil.toXml(wxRefundRequestBean, WxRefundRequestBean.class),
ContentType.create(ContentType.APPLICATION_XML.getMimeType(), "UTF-8"));
String postResult = null;
try {
// 这里发送请求,得到微信的返回值,值得注意的是微信退款的异步回调通知中返回的数据是加密过得
postResult = executor.execute(request).returnContent().asString();
} catch (IOException e) {
logger.error("微信支付退款申请失败:{}", e.getMessage());
e.printStackTrace();
return ResponseData.fail("微信支付退款申请失败");
}
logger.info(">>>>>>>>>>>>微信申请退款结果返回:{}", postResult);
4.到此微信退款的功能就完毕了,这里主要写的就是证书绑定这一块,其他部分都省略了,望大家谅解。当然,值得注意的是微信退款的异步回调通知中返回的数据是加密过得:
这里我也贴一下解密的代码吧,相对还是比较简单的
public static String decryptData(String base64Data) throws Exception {
// 这里的 base64Data 为上图中 req_info 的值
Security.addProvider(new BouncyCastleProvider());
Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING, "BC");
// 这里的 paySign 为微信分配的秘钥key,做微信支付的相信大家都知道
String key = new SecretKeySpec(MD5Util.MD5Encode(paySign, "UTF-8").toLowerCase().getBytes(), ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, key);
return new String(cipher.doFinal(Base64Util.decode(base64Data)));
}
到这来就全部结束了,希望能给碰到这块问题的人带来一点帮助。
转载请注明出处,谢谢了。