package net.dunotech.mercury.mtzx.Test;
import net.dunotech.mercury.mtzx.logger.MyLogger;
import net.dunotech.mercury.mtzx.logger.MyLoggerFactory;
import net.dunotech.mercury.mtzx.utils.WXPayXmlUtil;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.net.ssl.SSLContext;
import javax.xml.parsers.DocumentBuilder;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.cert.CertificateException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
* @author MTZX on 19/11/11 0011
*/
public class Test2 {
private static MyLogger logger = MyLoggerFactory.getMyLogger(Test.class);
public Map<String, String> refund(int refundFee) {
Map<String, Object> signMap = new HashMap<>(10);
String mchId = "【MCHID】";
signMap.put("appid", "【APPID】");
signMap.put("mch_id", mchId);
signMap.put("nonce_str", "32随机数");
// 以下transaction_id和out_trade_no二选一
//signMap.put("transaction_id", "支付成功时微信返回的transaction_id");
signMap.put("out_trade_no", "支付时自己这边生成的订单号");
signMap.put("out_refund_no", "32随机数");
signMap.put("refund_fee", "需要退款的金额,单位:分");
signMap.put("total_fee", "订单支付时的总金额,单位:分");
signMap.put("notify_url", "退款回调地址,退成成功微信支付会请求这个地址");
// 对数据进行签名
signMap.put("sign", dataSign("【APIKEY】", signMap));
String xml = WXPayXmlUtil.mapToXml(signMap);
if (isEmpty(xml)) {
logger.error("生成的申请退款信息错误");
return new HashMap<>(0);
}
logger.info("加载证书开始=========================================》》》》》");
StringBuilder sb2 = new StringBuilder();
FileInputStream instream = null;
try {
// 指定读取证书格式为PKCS12
KeyStore keyStore = KeyStore.getInstance("PKCS12");
// 读取本机存放的PKCS12证书文件
instream = new FileInputStream(new File("/projects/microcourse/cert/apiclient_cert.p12"));
// 指定PKCS12的密码(商户ID)
keyStore.load(instream, mchId.toCharArray());
// ssl双向验证发送http请求报文
SSLContext sslcontext = null;
sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mchId.toCharArray()).build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1"}, null,
SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
HttpPost httppost = new HttpPost("https://api.mch.weixin.qq.com/secapi/pay/refund");
StringEntity se = new StringEntity(xml, "UTF-8");
httppost.setEntity(se);
CloseableHttpResponse responseEntry = null;
String xmlStr2 = null;
responseEntry = httpclient.execute(httppost);
HttpEntity httpEntity = responseEntry.getEntity();
if (httpEntity != null) {
BufferedReader bufferedReader = null;
bufferedReader = new BufferedReader(new InputStreamReader(httpEntity.getContent(),
StandardCharsets.UTF_8));
while ((xmlStr2 = bufferedReader.readLine()) != null) {
sb2.append(xmlStr2);
}
}
} catch (IOException | CertificateException | NoSuchAlgorithmException | KeyStoreException | UnrecoverableKeyException | KeyManagementException e) {
logger.error("异常", e);
return new HashMap<>(0);
} finally {
try {
Objects.requireNonNull(instream).close();
} catch (IOException e) {
logger.error("异常", e);
}
}
Map<String, String> map;
try {
logger.info("返回请求结果=" + sb2.toString());
map = xmlToMap(sb2.toString());
} catch (Exception e) {
logger.error("异常", e);
return new HashMap<>(0);
}
if (map == null || map.size() == 0) {
logger.error("错误:生成的申请退款信息错误");
return new HashMap<>(0);
}
logger.info("申请退款接口返回的结果集======>" + map);
if ("SUCCESS".equalsIgnoreCase(map.get("return_code")) && "SUCCESS".equalsIgnoreCase(map.get("result_code"))) {
logger.info("****************退款申请成功!**********************");
return map;
} else {
logger.error("*****************退款申请失败!*********************");
return map;
}
}
/**
* XML格式字符串转换为Map
*
* @param strXML XML字符串
* @return XML数据转换后的Map
* @throws Exception
*/
public static Map<String, String> xmlToMap(String strXML) throws Exception {
try {
Map<String, String> data = new HashMap<>();
DocumentBuilder documentBuilder = WXPayXmlUtil.newDocumentBuilder();
InputStream stream = new ByteArrayInputStream(strXML.getBytes(StandardCharsets.UTF_8));
org.w3c.dom.Document doc = documentBuilder.parse(stream);
doc.getDocumentElement().normalize();
NodeList nodeList = doc.getDocumentElement().getChildNodes();
for (int idx = 0; idx < nodeList.getLength(); ++idx) {
Node node = nodeList.item(idx);
if (node.getNodeType() == Node.ELEMENT_NODE) {
org.w3c.dom.Element element = (org.w3c.dom.Element) node;
data.put(element.getNodeName(), element.getTextContent());
}
}
try {
stream.close();
} catch (Exception ex) {
logger.error("异常 ", ex);
}
return data;
} catch (Exception ex) {
logger.error("Invalid XML, can not convert to map. Error message: {}. XML content: {}", ex.getMessage(),
strXML);
throw ex;
}
}
private String dataSign(String key, Map signMap) {
String appid = objectToString(signMap.get("appid"));
String mchId = objectToString(signMap.get("mch_id"));
String nonceStr = objectToString(signMap.get("nonce_str"));
String notifyUrl = objectToString(signMap.get("notify_url"));
String outRefundNo = objectToString(signMap.get("out_refund_no"));
String outTradeNo = objectToString(signMap.get("out_trade_no"));
String refundFee = objectToString(signMap.get("refund_fee"));
//String subMchId = objectToString(signMap.get("sub_mch_id"));
String totalFee = objectToString(signMap.get("total_fee"));
String transactionId = objectToString(signMap.get("transaction_id"));
StringBuilder stringBuilder = new StringBuilder();
if (isNotEmpty(appid)) {
stringBuilder.append("appid=").append(appid);
}
if (isNotEmpty(mchId)) {
stringBuilder.append("&mch_id=").append(mchId);
}
if (isNotEmpty(nonceStr)) {
stringBuilder.append("&nonce_str=").append(nonceStr);
}
if (isNotEmpty(notifyUrl)) {
stringBuilder.append("¬ify_url=").append(notifyUrl);
}
if (isNotEmpty(outRefundNo)) {
stringBuilder.append("&out_refund_no=").append(outRefundNo);
}
if (isNotEmpty(outTradeNo)) {
stringBuilder.append("&out_trade_no=").append(outTradeNo);
}
if (isNotEmpty(refundFee)) {
stringBuilder.append("&refund_fee=").append(refundFee);
}
if (isNotEmpty(totalFee)) {
stringBuilder.append("&total_fee=").append(totalFee);
}
if (isNotEmpty(transactionId)) {
stringBuilder.append("&transaction_id=").append(transactionId);
}
stringBuilder.append("&key=").append(key);
try {
return MD5(stringBuilder.toString());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private String MD5(String data) throws Exception {
java.security.MessageDigest md = MessageDigest.getInstance("MD5");
byte[] array = md.digest(data.getBytes(StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
for (byte item : array) {
sb.append(Integer.toHexString((item & 0xFF) | 0x100), 1, 3);
}
return sb.toString().toUpperCase();
}
public static String objectToString(Object object) {
if (object == null) {
return null;
}
return String.valueOf(object);
}
public static boolean isEmpty(String string) {
return string == null || string.replaceAll(" ", "").trim().length() == 0;
}
public static boolean isNotEmpty(String string) {
return !isEmpty(string);
}
}
微信公众号支付后申请退款代码
最新推荐文章于 2022-12-18 21:24:19 发布