调用微信对账单接口
public static void main(String[] args) throws Exception {
// 随机数
String str = WXPayUtil.generateNonceStr();
// data
Map<String, String> data = new LinkedHashMap<>();
// Map<String, String> data1 = new LinkedHashMap<>();
data.put("appid", APPID);
data.put("bill_date", "20191111");
data.put("bill_type", "ALL");
data.put("mch_id", MCH_ID);
data.put("nonce_str", str);
data.put("tar_type", "GZIP");
String sign = WXPayUtil.generateSignature(data, API_KEY);
data.put("sign", sign);
System.out.println(sign);
System.out.println(WXPayUtil.mapToXml(data));
String result = SendPost.post(WXPayUtil.mapToXml(data), 6000, 6000);
// System.out.println("result"+WXPayUtil.xmlToMap(result));
System.out.println(result);
if (result.startsWith("<xml>") || result.contains("error_code")) {
System.out.println("无数据或者日期错误");
} else {
// 获取表头以外的其他内容:交易记录、汇总表头、汇总数据
String otherContent = result.substring(result.indexOf("`"));
System.out.println("otherContent" + otherContent);
// 获取交易记录
String records = otherContent.substring(0, otherContent.indexOf("总"));
String[] total = records.split("
");
for (int i = 0; i < total.length; i++) {
String[] order = total[i].replace("`", "").split(",");
System.out.println("order" + order[5]);
.....
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
随机数
/**
* 获取随机字符串 Nonce Str
*
* @return String 随机字符串
*/
public static String generateNonceStr() {
char[] nonceChars = new char[32];
for (int index = 0; index < nonceChars.length; ++index) {
nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length()));
}
return new String(nonceChars);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
生成sign签名
/**
* 生成签名
*
* @param data 待签名数据
* @param key API密钥
* @return 签名
*/
public static String generateSignature(final Map<String, String> data, String key) throws Exception {
return generateSignature(data, key, SignType.MD5);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
签名逻辑
/**
* 生成签名. 注意,若含有sign_type字段,必须和signType参数保持一致。
*
* @param data 待签名数据
* @param key API密钥
* @param signType 签名方式
* @return 签名
*/
public static String generateSignature(final Map<String, String> data, String key, SignType signType)
throws Exception {
Set<String> keySet = data.keySet();
String[] keyArray = keySet.toArray(new String[keySet.size()]);
Arrays.sort(keyArray);
StringBuilder sb = new StringBuilder();
for (String k : keyArray) {
if (k.equals(WXPayConstants.FIELD_SIGN)) {
continue;
}
if (data.get(k).trim().length() > 0) // 参数值为空,则不参与签名
sb.append(k).append("=").append(data.get(k).trim()).append("&");
}
sb.append("key=").append(key);
if (SignType.MD5.equals(signType)) {
return MD5(sb.toString()).toUpperCase();
} else if (SignType.HMACSHA256.equals(signType)) {
return HMACSHA256(sb.toString(), key);
} else {
throw new Exception(String.format("Invalid sign_type: %s", signType));
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
将map转化为xml
/**
* 将Map转换为XML格式的字符串
*
* @param data Map类型数据
* @return XML格式的字符串
* @throws Exception
*/
public static String mapToXml(Map<String, String> data) throws Exception {
org.w3c.dom.Document document = WXPayXmlUtil.newDocument();
org.w3c.dom.Element root = document.createElement("xml");
document.appendChild(root);
for (String key : data.keySet()) {
String value = data.get(key);
if (value == null) {
value = "";
}
value = value.trim();
org.w3c.dom.Element filed = document.createElement(key);
filed.appendChild(document.createTextNode(value));
root.appendChild(filed);
}
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
DOMSource source = new DOMSource(document);
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
transformer.transform(source, result);
String output = writer.getBuffer().toString(); // .replaceAll("
|
", "");
try {
writer.close();
} catch (Exception ex) {
}
return output;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
http post请求
/**
* post 请求
*
* @return
* @throws IOException
* @throws ClientProtocolException
*
*
*
*/
public static String post(String data, int readTimeoutMs, int connectTimeoutMs)
throws ClientProtocolException, IOException {
BasicHttpClientConnectionManager connManager = null;
HttpClient httpClient = HttpClientBuilder.create().setConnectionManager(connManager).build();
String url = "https://api.mch.weixin.qq.com/pay/downloadbill"; // 路径
HttpPost httpPost = new HttpPost(url);
// 是指连接时间
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(readTimeoutMs)
.setConnectTimeout(connectTimeoutMs).build();
httpPost.setConfig(requestConfig);
StringEntity postEntity = new StringEntity(data, "UTF-8");
httpPost.addHeader("Content-Type", "text/xml;charset=utf-8");
httpPost.addHeader("Accept-Encoding", "gzip,deflate");
// httpPost.addHeader("User-Agent", USER_AGENT + " " +
// config.getMchID());//10000100
httpPost.addHeader("User-Agent", USER_AGENT + " " + 1490714122);
httpPost.setEntity(postEntity);
HttpResponse httpResponse = httpClient.execute(httpPost);
// HttpEntity httpEntity = httpResponse.getEntity();
System.out.println(httpResponse);
Header[] headers = httpResponse.getHeaders("Content-Type");
boolean isGzip = false;
for (Header h : headers) {
if (h.getValue().equals("application/x-gzip")) {
// 返回头中含有gzip
isGzip = true;
}
}
if (isGzip) {
// 需要进行gzip解压处理
return EntityUtils.toString(new GzipDecompressingEntity(httpResponse.getEntity()), "UTF-8");
} else {
return EntityUtils.toString(httpResponse.getEntity());
}
// return EntityUtils.toString(httpEntity, "UTF-8");
}