金財通電子發票測試記錄


金財通有一只程式可以用來與她們的主機進行上/下傳交換檔(只能在Window裡運作),對於
使用Linux開發的人是非常的不便,一開始只好用cifs+autofs把Window的目錄mount進來,
後來臨上線才知道這只程式,只是和她們的FTPs主機(FileZilla)進行檔案同步,所以我得以
排除Window的不便利,首先想到的就是把遠端的FTPs主機跟Linux的目錄(/SCM)進行同步
首先取得測試憑證
$echo | sudo openssl s_client -connect 61.57.test.ip:990 | sudo openssl x509 -out /tmp/bankpro.pem
若是要mount 遠端目錄到本地 /ftp 目錄,並同步資料下到 /SCM後unmount
#以CentOS 7為例
$yum -y install curlftpfs rsync msmtp
$chcon -t sendmail_exec_t /usr/bin/msmtp
#取回憑證
$echo | sudo openssl s_client -connect 61.57.test.ip:990 | sudo openssl x509 -out /tmp/bankpro.pem
$mkdir /ftp /SCM
$cat ftp.sh
#!/bin/bash
curlftpfs -o ssl,cacert=/root/bankpro.pem,no_verify_peer,user=帳號:密碼 -f ftps://61.57.test.ip:990/ /ftp &
COUNTER=10
#檢查是否已 mount /ftp
mountpoint /ftp > /dev/null
while  [ $? != 0 -a $COUNTER > 0 ];do
   sleep 1
   let COUNTER-=1
   mountpoint /ftp > /dev/null
done
mountpoint /ftp > /dev/null
if [ $? == 0 ];then
  /bin/rsync -av /ftp/Download /SCM/Download && /bin/mv -f /ftp/Download/* /ftp/DownloadBackup/
  /bin/rsync -av /SCM/Upload /ftp/Upload
  sync
  fusermount -u /ftp
else
  echo "Subject:檢查金財通FTP主機失敗" | msmtp --host=192.168.mail.ip --port=25 --auth=off -f invoice@somewhere.com.tw -X /var/log/message 'kent@somewhere.com.tw'
fi
 然後我就可以對下載目錄(/SCM/Download)進行新進檔案監控即可
//開始時掃瞄既有檔案
try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(downloadPath, new DirectoryStream.Filter<Path>() {
   @Override
   public boolean accept(Path entry) throws IOException {
       return entry.getFileName().toString().startsWith(“統編” + "-O-") || entry.getFileName().toString().startsWith(“統編” + "-InvStatus-");
   }
})) {
   for (Path path : directoryStream) {
       doSomething4(path.getFileName());
   }
}
:其實上面的doSomething4是不對的,因應先把既有的檔案記住後立即啟動目錄監控,以免在掃瞄處理的過程中又有新檔
進來,上面只是為簡化過程而故意為之。
初始掃瞄完成後再監控下載目錄
WatchService watchService = FileSystems.getDefault().newWatchService();
downloadPath.register(watchService, StandardWatchEventKinds.ENTRY_CREATE);
while (!isTerminated()) {
   WatchKey key = watchService.take();//若沒有觸發,則會停在此地等待新檔進入
   for (WatchEvent<?> event : key.pollEvents()) {
      WatchEvent.Kind kind = event.kind();
      if (kind == StandardWatchEventKinds.OVERFLOW) {
          continue;
      }
      WatchEvent<Path> ev = cast(event);
      doSomething4(downloadPath.resolve(ev.context()));
   }
   if (!key.reset()) {
       logger.fatal("監控失效!!!");
   }
}

另外一種做法就是自行寫程式
首先要將測試憑證轉成Java KeyStore,執行以下指令後把JKS放到classpath中
$openssl x509 -outform der -in bankpro.pem -out bankpro.der
$keytool -import -alias bankpro.com.tw -keystore bankpro.jks -file bankpro.der
輸入金鑰儲存庫密碼:  自訂keystore密碼
重新輸入新密碼:自訂keystore密碼
信任這個憑證? [否]:  y
憑證已新增至金鑰儲存庫中
使用Commons-net連到FTP主機
KeyStore keyStore = KeyStore.getInstance("JKS");
try (InputStream is = Main.class.getResourceAsStream("/bankpro.jks")) {
   keyStore.load(is, 自訂keystore密碼”.toCharArray());
}
X509TrustManager defaultTrustManager = TrustManagerUtils.getDefaultTrustManager(keyStore);
FTPSClient ftps = new FTPSClient(“TLS”, false);
ftps.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out)));
ftps.setTrustManager(defaultTrustManager);
ftps.connect("61.57.test.ip");
ftps.enterLocalPassiveMode();
if (!FTPReply.isPositiveCompletion(ftps.getReplyCode())) {
   ftps.disconnect();
} else {
   if (ftps.login("帳號", "密碼")) {
       ftps.execPBSZ(0);
       ftps.execPROT("P");
       ftps.type(FTP.ASCII_FILE_TYPE)
       ftps.pasv()
       ftps.setBufferSize(1000);
       for (FTPFile file : ftps.listFiles("/Download")) {
           logger.debug("{}:{}", file.isDirectory() ? "目錄" : file.isFile() ? "檔案" : "未知", file.getName());
           if(file.isFile()){//下載檔案(當然也可以直接開啟串流讀取內容)
               ftps.retrieveFile("/Download/"+file.getName(),Files.newOutputStream(Paths.get("/tmp", file.getName()), StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE));
           }
       }
   }
}

留言

這個網誌中的熱門文章

企業人員的統一管理-FreeIPA學習筆記

證交所最佳五檔的程式解析

Postgresql HA