微信对账文件处理之文件模式

一、查看接口

项目中要进行对微信支付的账单进行对账,网上查一了一下,基本上所有的模式都是直接调用返回字符串的模式。微信官方接口如下微信对账官方接口
微信对账
我们可以看到,其中有一个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();
            }
        }

解压过程是拿到全路径文件地址(包括文件名),解压也是全路径
在这里插入图片描述
成功
在这里插入图片描述
就此完毕,下面就是读取文件,千篇一律了,不做详细介绍了,告辞!

发布了17 篇原创文章 · 获赞 8 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/Charles_lxx/article/details/105425994
今日推荐