生成對帳文件_實現

 

我方天天在服務器上生成對帳文件, 第三方來取.java

 

1.需求:git

 

 

 

2.思路sql

生成對帳文件的程序是一個定時任務: 凌晨2點運行此程序
1.設置好 對帳文件存放的路徑(工程部門給外部平臺一個地址,他們本身過來取)
2.在這個路徑下新建一個文件 .  格式是.txt
3. 鏈接數據庫,查詢支付表(可能多表查詢), 查詢前一天的數據. 按照接口文檔須要的字段  查詢到對應字段 ,並拼接
4.把查出來的數據(eg:101486120190325083431|20190325|10.00|0|1|0042930413|SWShopMall),  放到  .txt文件裏

 

 
 
 
3.代碼
package com.seaway.open.open_bank_luoyang_check;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.yaml.snakeyaml.Yaml;

import com.seaway.open.open_bank_luoyang_check.configure.Configure;

import io.vertx.core.AbstractVerticle;
import io.vertx.core.Vertx;
import io.vertx.core.cli.Argument;
import io.vertx.core.cli.CLI;
import io.vertx.core.cli.TypedOption;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.jdbc.JDBCClient;
import io.vertx.ext.jdbc.spi.impl.HikariCPDataSourceProvider;
import io.vertx.ext.sql.ResultSet;
import io.vertx.ext.sql.SQLConnection;

public class Runner extends AbstractVerticle {
    private static final Logger logger = LogManager.getLogger(Runner.class);
    private Configure gconfigure = null;
    private JDBCClient jdbcClient = null;

    // Vertx vertx = Vertx.vertx();
    public Configure getGconfigure() {
        return gconfigure;
    }

    public void setGconfigure(Configure gconfigure) {
        this.gconfigure = gconfigure;
    }

    public synchronized JDBCClient getJdbcClientInstance() {

        if (jdbcClient == null) {
            try {
                HikariCPDataSourceProvider HikariCPDataSource = new HikariCPDataSourceProvider();

                JsonObject jdbcobject = JsonObject.mapFrom(getGconfigure().getJdbcConfig());

                jdbcobject.put("autoCommit", true);

                jdbcClient = JDBCClient.create(vertx, HikariCPDataSource.getDataSource(jdbcobject));
                logger.info("初始化數據庫鏈接池成功 {}", jdbcobject.toString());

            } catch (SQLException e) {
                logger.error("鏈接數據庫失敗:{}", e);
            }
        }
        return jdbcClient;
    }

    public static void main(String[] args) {
        Runner runner = new Runner();
        Vertx vertx = Vertx.vertx();
        runner.start(vertx);

    }

    private void initConfigure() {
        CLI cli = CLI.create("open_bank_luoyang_check").setSummary("開放平臺xx銀行對帳文件生成程序")
                .addOption(new TypedOption<Boolean>().setType(Boolean.class).setLongName("configure")
                        .setShortName("cfg").setDescription("指定配置文件").setFlag(true).setRequired(true))
                .addArgument(new Argument().setDescription("文件絕對路徑(yaml格式)").setArgName("filename").setRequired(true));

        StringBuilder builder = new StringBuilder();
        cli.usage(builder);

        String ConfigureFile = null;
        // int liFile = this.context.processArgs().indexOf("-cfg");
        // if (liFile == -1) {
        //
        // logger.error("指定配置文件: [-cfg <filename>]");
        // logger.error(builder);
        // stop();
        // }
        // try {
        // ConfigureFile = this.context.processArgs().get(liFile + 1);
        // if (!new File(ConfigureFile).exists()) {
        //
        // logger.error("配置文件[" + ConfigureFile + "]不存在");
        // logger.error(builder);
        // stop();
        // }
        // } catch (Exception e) {
        //
        // logger.error("指定配置文件: [-cfg <filename>]",e);
        // logger.error(builder);
        // stop();
        //
        // }
        Yaml yaml = new Yaml();
        ConfigureFile = "F:/Users/Administrator/git/open6/open_bank_check/open_bank_luoyang_check/src/main/resources/open_bank_luoyang_check.yaml";
        try {
            InputStream in = new FileInputStream(new File(ConfigureFile));
            setGconfigure(yaml.loadAs(in, Configure.class));
            logger.info("讀取配置文件[" + ConfigureFile + "]:[" + getGconfigure() + "]");
        } catch (Exception e) {
            logger.error("解析文件錯誤", e);
            stop();
        }

    }

    @Override
    public void stop() {
        logger.info("關閉系統!");
        vertx.close();

        System.exit(0);
    }

    // @Override
    public void start(Vertx vertx) {

        initConfigure();

        HikariCPDataSourceProvider HikariCPDataSource = new HikariCPDataSourceProvider();
        try {
            JsonObject jdbcobject = JsonObject.mapFrom(getGconfigure().getJdbcConfig());

            jdbcobject.put("autoCommit", true);

            jdbcClient = JDBCClient.create(vertx, HikariCPDataSource.getDataSource(jdbcobject));
            logger.info("初始化數據庫鏈接池成功 {}", jdbcobject.toString());

        } catch (SQLException e) {
            logger.error("鏈接數據庫失敗:", e);
        }

        /**
         * 功能描述: 當天對前一天生活圈發生的支付或退款交易進行校對和清算 對帳文件的文件名:SWShopMall_yyyyMMdd.txt 文件內容格式: 訂單號
         * |交易日期|金額|交易狀態|交易類型|客戶號 |商戶號 20160602 |20190218|9.01| 0 | 1 | 037894566
         * |SWShopMall 文件格式是.txt 文件中不能出現空格,空行 天天早上7點以前必須將前一天的對帳文件放置服務器上,不然將影響對帳交易 交易狀態
         * 0:成功1:失敗 交易類型 1:付款2:退款;
         */

        // 每晚2點生成
        vertx.setTimer(getGconfigure().getFileConfigure().getTaskTime(), id1 -> {
            executeTask();
            vertx.setPeriodic(getGconfigure().getFileConfigure().getCycleTaskTime(), id2 -> {
                executeTask();
            });
            vertx.cancelTimer(id1);
        });

    }

    private void executeTask() {
        logger.info("定時任務開始");
        String dateTime = LocalDateTime.now().minusDays(1).format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        // 若是dateTime日期20190324時間小於設置的時間,則取配置時間
        if (!getGconfigure().getCheckConfigure().getCheckDate().equals("00000000"))
            dateTime = getGconfigure().getCheckConfigure().getCheckDate();

        String checkPath = getGconfigure().getCheckConfigure().getCheckPath();
        String filePath = checkPath + "/SWShopMall_" + dateTime + ".txt";
        logger.info("filePath: {}", filePath);
        File file = new File(filePath);
        if (file.exists()) {
            logger.info("文件已經生成 退出");
            return;
        } else {
            logger.info("文件不存在 新建文件");
            try {
                file.createNewFile();
                logger.info("建立成功");

                if (jdbcClient == null) {
                    logger.info("jdbcClient is null getJdbcClientInstance");
                    jdbcClient = getJdbcClientInstance();
                } else {
                    logger.info("jdbcClient not null");
                }
                String times = dateTime;
                jdbcClient.getConnection(jdbcConnect -> {
                    if (jdbcConnect.failed()) {
                        logger.error("鏈接出錯: {}", jdbcConnect.cause().getMessage());
                        return;
                    } else {
                        final SQLConnection connection = jdbcConnect.result();
                        logger.info("取得鏈接");
                        // 查詢數據庫
                        String beginTime = times + "000000";
                        String endTime = times + "235959";
                        // 金額保留兩位小數,多餘舍掉 cast(trunc(pay_amount/10000,2) AS NUMBER (10, 2))
                        // 金額保留兩位小數,四捨五入 to_char(pa.pay_amount/10000,'fm99,999,990.00')
                        // 該sql金額會至少保留兩位小數(單位元)
                        String querySql = "\n\nselect pay_id || '|' || substr(pay_time, 0, 8) || '|'  || \n"
                                + "case  \n" + "  when substr(to_char(pay_amount/10000,'fm99,999,990.0000'),-2) > 00\n"
                                + "  then\n" + "       to_char(pay_amount/10000,'fm99,999,990.0000')\n" + "  else\n"
                                + "       to_char(pay_amount/10000,'fm99,999,990.00')\n" + "  end \n" + "  || '|' ||\n"
                                + "case  when stats in(3,5,9) then\n" + "          0\n" + "         else\n"
                                + "          1\n" + "       end || '|' || 1 || '|' || user_id || '|' || '"
                                + getGconfigure().getFileConfigure().getMerchantCode() + "'\n"
                                + "from payment_item where pay_time between '" + beginTime + "' and '" + endTime
                                + "'  and  gateway_id = '" + getGconfigure().getFileConfigure().getGateway_id()
                                + "'  and channel_id = '" + getGconfigure().getFileConfigure().getChannel_id() + "' \n"
                                + "union all\n" + "select r.refund_id || '|' || substr(r.refund_time, 0, 8)|| '|' || \n"
                                + "case  \n"
                                + "  when substr(to_char(r.refund_amount/10000,'fm99,999,990.0000'),-2) > 00\n"
                                + "  then\n" + "       to_char(r.refund_amount/10000,'fm99,999,990.0000')\n"
                                + "  else\n" + "       to_char(r.refund_amount/10000,'fm99,999,990.00')\n" + "  end \n"
                                + "|| '|' ||\n" + "case r.stats \n" + "         when 1 then\n" + "          0\n"
                                + "         when 2 then\n" + "          1\n" + "         else\n" + "          1\n"
                                + "       end || '|' || 2 || '|' || p.user_id || '|' || '"
                                + getGconfigure().getFileConfigure().getMerchantCode() + "'\n"
                                + "from refund_item r,payment_item p   \n"
                                + "where r.pay_id = p.pay_id and r.refund_time between '" + beginTime + "' and '"
                                + endTime + "'  and  r.gateway_id = '"
                                + getGconfigure().getFileConfigure().getGateway_id() + "'  and r.channel_id = '"
                                + getGconfigure().getFileConfigure().getChannel_id() + "'\n";
                        logger.info("querySql: {}", querySql);
                        connection.query(querySql, queryresult -> {
                            if (queryresult.succeeded()) {
                                connection.close();
                                logger.info("queryresult succeeded");
                                ResultSet queryResultSet = queryresult.result();
                                List<JsonArray> jsonArraysList = queryResultSet.getResults();
                                // logger.info("jsonArraysList: {}", jsonArraysList);
                                FileOutputStream outSTr = null;
                                BufferedOutputStream buff = null;
                                try {
                                    outSTr = new FileOutputStream(file);
                                } catch (FileNotFoundException e1) {
                                    logger.error(e1);
                                }
                                buff = new BufferedOutputStream(outSTr);
                                logger.info("size: " + jsonArraysList.size());
                                for (int i = 0; i < jsonArraysList.size(); i++) {
                                    /*** 把數據寫入到磁盤 */
                                    try {
                                        buff.write((jsonArraysList.get(i).getString(0) + "\n").getBytes());
                                        // 每多少次清理一次 緩衝區
                                        if (i % getGconfigure().getFileConfigure().getFlushCount() == 0
                                                && buff != null) {
                                            buff.flush();
                                            logger.info("flush: " + i);
                                        }
                                    } catch (IOException e) {
                                        logger.error("寫入磁盤出錯", e);

                                    }
                                }

                                if (buff != null) {
                                    try {
                                        buff.flush();
                                        buff.close();
                                    } catch (IOException e) {
                                        logger.error("關閉出錯", e);
                                    }
                                }
                                logger.info("{}日對帳文件寫入磁盤成功,共{}條", times, jsonArraysList.size());
                            } else {
                                connection.close();
                                logger.error("執行查詢錯誤,關閉鏈接: {}", queryresult.cause().getMessage());
                            }
                        });
                    }
                });
            } catch (IOException e) {
                logger.error("程序異常: ", e);
            }
        }
    }
}

 

 

控制檯運行此程序,對帳文件生成數據庫

.........................apache

......................json

 

 

 去這個路徑下看看,發現對帳文件已經生成了服務器

 

有bug--回頭看發現程序裏面須要一個回車符oracle

 

 

 

 

4.補充ide

這個程序重點:函數

1.要熟悉java基礎.(建文件 /往文件寫數據)

2.sql函數的運用.

公司數據庫用的是oracle數據庫.  下面是把生成對帳文件內容的sql 從程序裏摘出來.你們能夠學習下

select pay_id || '|' || substr(pay_time, 0, 8) || '|'  || 
case  
  when substr(to_char(pay_amount/10000,'fm99,999,990.0000'),-2) > 00
  then
       to_char(pay_amount/10000,'fm99,999,990.0000')
  else
       to_char(pay_amount/10000,'fm99,999,990.00')
  end 
  || '|' ||
case  when stats in(3,5,9) then
          0
         else
          1
       end || '|' || 1 || '|' || user_id || '|' || 'SWShopMall'
from payment_item where pay_time between '20190326000000' and '20190326235959'  and  gateway_id = '10'  and channel_id = '1' 
union all
select r.refund_id || '|' || substr(r.refund_time, 0, 8)|| '|' || 
case  
  when substr(to_char(r.refund_amount/10000,'fm99,999,990.0000'),-2) > 00
  then
       to_char(r.refund_amount/10000,'fm99,999,990.0000')
  else
       to_char(r.refund_amount/10000,'fm99,999,990.00')
  end 
|| '|' ||
case r.stats 
         when 1 then
          0
         when 2 then
          1
         else
          1
       end || '|' || 2 || '|' || p.user_id || '|' || 'SWShopMall'
from refund_item r,payment_item p   
where r.pay_id = p.pay_id and r.refund_time between '20190326000000' and '20190326235959'  and  r.gateway_id = '10'  and r.channel_id = '1'

在數據庫運行該sql, 這個就是對帳文件裏面放的內容. 已經用sql拼接好了.

 

 

  多加思考,多加訓練.

 

 

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~補充二~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

上面的sql太長了, 是怎麼要達到我想要的內容呢

1.先查出接口文檔中字段(對帳文件須要的字段).

標準的文件內容格式:
20160602|20190218|9.01|0|1|037894566|SWShopMal

 

 

2.而後再根據需求 改.  加函數/  加判斷

eg:時間格式 /   金額顯示格式(保留幾位小數) /  只顯示渠道的支付記錄/   等等

相關文章
相關標籤/搜索