一、查看接口
項目中要進行對微信支付的賬單進行對賬,網上查一了一下,基本上所有的模式都是直接調用返回字符串的模式。微信官方接口如下微信對賬官方接口
我們可以看到,其中有一個tar_type字段,網上大部分的對賬單下載都是字符串格式進行處理,也就是說tar_type是不用傳的,那麼我就想,如果字符串數據過大,可能會造成數據的丟失,那麼遠不如下載文件來的方便。
我這裏使用的是 XXL-JOB 進行定時下載處理文件。話不多說,上代碼。
二、定時下載
首先定時機制將在後面介紹,這裏就直接截圖處理了
下面進行下載微信的對賬文件,我們也看到了,其格式要求爲GZIP的,之前我也直接存過ZIP,但是代碼解壓不出來,windows上直接手動解壓可以,再手動壓縮用代碼解壓也可以。就是下載後直接解壓告訴我們不是ZIP文件,所以這裏必須要保存它的原來的 .gzip 格式。
下面是文件的下載:
/**
* 文件格式的微信對賬單
*
* @param mchnt
* @throws Exception
*/
public void downWxpayBill(PaygatewayMchnt mchnt) throws Exception {
// 拿微信的參數
String wxPayKey ="微信支付時的商戶祕鑰KEY";
String wxMchntId = "微信支付時候的商戶號";
String wxAppaId = "微信支付時候的商戶APPID";
// 實例化當天的日期
Date today = new Date();
// 用當天的日期減去24小時得到昨天的日期
Date yesterdayDate = new Date(today.getTime() - 86400000L);
// 將昨天日期解析成字符串
String billDate = new SimpleDateFormat("yyyyMMdd").format(yesterdayDate);
MyConfig config = new MyConfig(wxPayKey, wxMchntId, wxAppaId);
// 微信公共參數封裝
WXPay wxpay = new WXPay(config);
// 讀取公共參數並創建處理對象
Map<String, String> paramMap = new HashMap<String, String>();
// 對賬單日期 格式:20140603
paramMap.put("bill_date", billDate);
// 隨機字符串
paramMap.put("nonce_str", WXPayUtil.generateNonceStr());
paramMap.put("bill_type", "ALL");// 賬單類型 ALL SUCCESS REFUND RECHARGE_REFUND
paramMap.put("tar_type", "GZIP");//文件格式
String sign = WXPayUtil.generateSignature(paramMap, wxPayKey);
paramMap.put("sign", sign);// 簽名
//微信SDK的下載對賬單
/****************START*********************/
Map<String, String> respMap = wxpay.downloadBill(paramMap);
String wxbillPath = propertiesDIY.getFile_path_wxpay();
//判斷有沒有文件
if (("SUCCESS").equals(respMap.get("return_code")) && ("ok").equals(respMap.get("return_msg"))) {
logger.debug("success for wxpay bill");
//這時候打印的返回內容是亂碼,我們不用理會
String requestXml = WXPayUtil.mapToXml(paramMap);
String filePath = wxbillPath + File.separator + mchnt.getMchntId() + "-" + billDate + ".gzip";
//準備下載
HttpClientUtil.downWxpayBill(WXPayConstants.DOWNLLOAD_BIILLURL, filePath, requestXml);
logger.debug("download success:[" + mchnt.getInstId() + mchnt.getMchntId() + "-" + billDate + ".gzip]");
} else if (("No Bill Exist").equals(respMap.get("return_msg"))) {
logger.debug("no wxpay bill:[" + mchnt.getInstId() + "-" + mchnt.getMchntId() + "-" + billDate + "]");
} else {
logger.error("call wxpay for bills fail:[" + mchnt.getInstId() + "-" + mchnt.getMchntId() + "-" + billDate + "]");
}
/****************END********************/
//把文件全都移走到
List<String> files = FileUtil
.getFile(new File(wxbillPath + File.separator + propertiesDIY.getFile_path_recvtmp()));
if (files.size() != 0) {
for (String filename : files) {
FileUtil.MoveFile(wxbillPath + File.separator + propertiesDIY.getFile_path_recvtmp(), wxbillPath + File.separator + propertiesDIY.getFile_path_recv(), filename);
}
}
}
上面的START–END可以不需要的,我這裏是判斷了一下有沒有對賬單來判斷要不要下載,實際上請求判斷+下載是兩次請求過程了。
下面給出downWxpayBill工具類,其中
WXPayConstants.DOWNLLOAD_BIILLURL=https://api.mch.weixin.qq.com/pay/downloadbill
微信對賬單地址
/**
* 微信對賬
*
* @param Url
* @param savePath
* @param requestXml
*/
public static void downWxpayBill(String Url, String savePath, String requestXml) {
// 設置訪問地址
URL url = null;
HttpURLConnection httpURLConnection = null;
InputStream inputStream = null;
FileOutputStream fos = null;
try {
url = new URL(Url);
// http的連接類 得到網絡訪問對象
httpURLConnection = (HttpURLConnection) url.openConnection();
// 設置請求參數(訪問方式,超時時間,輸入,輸出流,請求頭信息),以流的形式進行連接
// 設定請求的方法,默認是GET
httpURLConnection.setRequestMethod("POST");
// 超時時間
httpURLConnection.setConnectTimeout(5000);
// 設置是否向HttpURLConnection輸出
httpURLConnection.setDoOutput(true);
// 設置是否從httpUrlConnection讀入
httpURLConnection.setDoInput(true);
// 設置使用編碼格式參數的名-值對
httpURLConnection.setRequestProperty("Content-Type", "application/json;charset=utf-8");
httpURLConnection.setRequestProperty("Charsert", "UTF-8");
// 簡歷連接
httpURLConnection.connect();
if (requestXml != null && requestXml != "") {
// 寫入參數到請求中
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(httpURLConnection.getOutputStream(), "UTF-8"));
// 傳遞參數
writer.write(requestXml.toString());
writer.flush();
writer.close();
}
// 獲取響應code 200成功
int code = httpURLConnection.getResponseCode();
if (code == 200) {
inputStream = httpURLConnection.getInputStream();
// 判斷字節大小
if (inputStream.available() != 0) {
File file = new File(savePath);
if (!file.getParentFile().exists()) {
boolean result = file.getParentFile().mkdirs();
if (!result) {
logger.error("creat file fail");
}
}
byte[] temp = new byte[2048];
int b;
fos = new FileOutputStream(file);
while ((b = inputStream.read(temp)) != -1) {
fos.write(temp, 0, b);
fos.flush();
}
}
}
// 關閉 http連接,釋放資源
httpURLConnection.disconnect();
} catch (IOException e) {
logger.error("ERR:", e);
} finally {
//最終都執行關流
try {
if (inputStream != null)
inputStream.close();
if (fos != null)
fos.close();
if (httpURLConnection != null)
httpURLConnection.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
}
三、解壓下載文件
這時候我們執行下載後,會下載下圖的文件,看起來想txt的是因爲可以用txt打開
我們用UE或者txt打開都是亂碼,最主要的是,windows沒有自帶gzip文件的解壓格式,用的其他軟件也沒有。這爲我們的工作帶來的困難。因爲我不知道下載的是不是我們需要的。
下面就直接進行解壓操作看一下,文件裏的內容是不是我們想要的。
GZIPInputStream ginm = null;
BufferedReader reader = null;
FileOutputStream fos = null;
int lineCount = 0;
try {
//zipFilePath爲壓縮包在的全路徑
ginm = new GZIPInputStream(new FileInputStream(zipFilePath));
reader = new BufferedReader(new InputStreamReader(ginm, "UTF-8"));
String lineCon;
//filePath爲要解壓的全稱,包括文件名,我這裏是方便後面操作也可以改爲txt格式
fos = new FileOutputStream(filePath + File.separator + gzipName.substring(0, 29));
while ((lineCon = reader.readLine()) != null) {
//這裏加一個\n是因爲讀取的文件都是一行,我們給他區別行,方便讀取
fos.write((lineCon + "\n").getBytes());
lineCount++;
}
ginm.close();
reader.close();
fos.close();
} catch (Exception e) {
logger.error("UnGzip fail", e);
} finally {
if (null != reader) {
reader.close();
}
if (null != fos) {
fos.close();
}
if (null != ginm) {
ginm.close();
}
}
解壓過程是拿到全路徑文件地址(包括文件名),解壓也是全路徑
成功
就此完畢,下面就是讀取文件,千篇一律了,不做詳細介紹了,告辭!