微信對賬文件處理之文件模式

一、查看接口

項目中要進行對微信支付的賬單進行對賬,網上查一了一下,基本上所有的模式都是直接調用返回字符串的模式。微信官方接口如下微信對賬官方接口
微信對賬
我們可以看到,其中有一個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();
            }
        }

解壓過程是拿到全路徑文件地址(包括文件名),解壓也是全路徑
在這裏插入圖片描述
成功
在這裏插入圖片描述
就此完畢,下面就是讀取文件,千篇一律了,不做詳細介紹了,告辭!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章