<dependency>
<groupId>org.apache.camelgroupId>
<artifactId>camel-ftpartifactId>
<version>2.13.2version>
dependency>
<dependency>
<groupId>net.sourceforge.javacsvgroupId>
<artifactId>javacsvartifactId>
<version>2.0version>
dependency>
/*
* Copyright 2019 Wicrenet, Inc. All rights reserved.
*/
package com.xy.pay.core.joint.lakla.trade.bill;
/**
* 【拉卡拉账单拉取】
*
* @author YJX
* Created on 2019-06-26 18:32
*/
import com.jcraft.jsch.*;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.Properties;
@Component
class LakLaBillDownload {
private static final Logger logger = LoggerFactory.getLogger(LakLaBillDownload.class);
private static final String SFTPPATH = "/sftp/bill/fzxya/"; // SFTP 拉卡拉服务器账单绝对路径
private static final String SFTPUSERNAME = "xxxxx"; // SFTP 拉卡拉用户名
private static final String SFTPHOST = "xxx.xxx.xxx"; // SFTP 拉卡拉账单服务器IP地址
private static final int SFTPPORT = 22; // SFTP 端口
private static final String SFTPPASSWORD = "xxxxx"; // SFTP 拉卡拉密码
/**
* 拉卡拉账单拉取
*
* @param sfileName 拉卡拉服务器账单名称
* @param billFile 自己公司服务器存拉卡拉账单路径
**/
static File downloadLaKLaBill(String sfileName, Resource billFile) {
try {
//远程主机绝对路径+文件名称 格式: /sftp/bill/fzxya/TF_机构号_YYYYMMDD.txt
String sftpBillResources = SFTPPATH + sfileName;
Session session;
Channel channel;
JSch jsch = new JSch();
session = jsch.getSession(SFTPUSERNAME, SFTPHOST, SFTPPORT);
session.setPassword(SFTPPASSWORD);
session.setTimeout(100000);
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
if (!session.isConnected()) {
session.connect();
}
channel = session.openChannel("sftp");
if (!channel.isConnected()) {
channel.connect();
}
ChannelSftp chSftp = (ChannelSftp) channel;
try {
// 将服务器指定文件转成流
InputStream inputStream = chSftp.get(sftpBillResources);
// 将流转成文件黏贴到billFile.getFile(保存到自己的服务器)
FileUtils.copyToFile(inputStream, billFile.getFile());
//返回文件流
return billFile.getFile();
} catch (SftpException fe) {
if (fe.toString().contains("No such file")) {
logger.error("拉卡拉账单拉取,拉卡拉服务器不存在该文件:{}", fe);
return null;
}
logger.error("卡拉账单拉取,错误:{}", fe);
} catch (UnsupportedEncodingException ue) {
logger.error("拉卡拉账单拉取,不支持的编码错误:{}", ue);
} catch (IOException ie) {
logger.error("拉卡拉账单拉取,IO错误:{}", ie);
} finally {
//关闭持久连接
chSftp.quit();
channel.disconnect();
session.disconnect();
}
return null;
} catch (JSchException jsche) {
logger.error("拉卡拉账单拉取,连接拉卡拉服务器错误:{}", jsche);
}
return null;
}
}
3 LaklaTradeBillService.java
package com.xy.pay.core.joint.lakla.trade.bill;
import com.xy.common.msg.Message;
import com.xy.common.msg.Msg;
import com.xy.common.verify.Asserts;
import com.xy.pay.core.PayEnvironment;
import com.xy.pay.core.exception.XyPayException;
import com.xy.pay.core.joint.JointTradeBillService;
import com.xy.pay.core.joint.lakla.LaklaTradeService;
import com.xy.pay.core.joint.lakla.model.LaklaTradeBill;
import com.xy.pay.core.joint.lakla.model.LaklaTradeBillResponse;
import com.xy.pay.core.structure.plugin.LakLaBillParseStrategy;
import org.joda.time.LocalDate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 拉卡拉账单下载
*
* @author YJX
* @date 2019/5/14 15:10
*/
@Service
@Qualifier("lakla")
public class LaklaTradeBillService extends LaklaTradeService implements JointTradeBillService<LaklaTradeBill, LaklaTradeBillResponse> {
private static final Logger logger = LoggerFactory.getLogger(LaklaTradeBillService.class);
@Autowired
private PayEnvironment payEnvironment;
private static final Lock LOCK = new ReentrantLock();
@Autowired(required = false)
private LakLaBillParseStrategy lakLaBillParseStrategy;
/**
* 账单下载
*/
@Override
public Msg<LaklaTradeBillResponse> download(LaklaTradeBill tradeBill) {
Asserts.notNull(tradeBill);
Asserts.notNull(tradeBill.getBill_date());
// 对账单文件格式:TF_机构号_YYYYMMDD.txt(YYYYMMDD为产生对账单的文件)
String fileName = "TF_829203_" + LocalDate.parse(tradeBill.getBill_date().toString()).toString("yyyyMMdd") + ".txt";
//没有配置下载路径,就不下载
if (this.payEnvironment.getLaklaBillDownloadPath() == null) {
throw new XyPayException("没有配置拉卡拉账单下载路径");
}
try {
String dirName = LocalDate.parse(tradeBill.getBill_date().toString()).toString("yyyy-MM-dd");
//创建目录
createDir(dirName);
//删除历史
removeHistoryBill(fileName, dirName);
//生成路径
Resource billFile = this.payEnvironment.getLaklaBillDownloadPath().createRelative(dirName + "/" + fileName);
File file = LakLaBillDownload.downloadLaKLaBill(fileName, billFile);
//请求账单生成
return this.lakLaBillParseStrategy.parse(file, tradeBill.getAppInfo().getAccount());
} catch (IOException e) {
logger.error("拉卡拉账单下载错误:{}", e);
}
return Message.getError("账单获取错误");
}
/**
* 创建目录,如果目录不存在
*/
private void createDir(String dirName) throws IOException {
Resource dirFile = this.payEnvironment.getLaklaBillDownloadPath().createRelative(dirName);
if (dirFile.exists() && dirFile.getFile().isDirectory()) {
return;
}
try {
Asserts.state(LOCK.tryLock(10, TimeUnit.SECONDS));
} catch (Exception e) {
logger.error(" 创建目录,如果目录不存在 - 获取锁失败", e);
}
try {
if (dirFile.exists() && dirFile.getFile().isDirectory()) {
return;
}
boolean flag = dirFile.getFile().mkdirs();
if (!flag) {
throw new IOException("拉卡拉账单-目录创建失败");
}
} finally {
LOCK.unlock();
}
}
/**
* 移除存在的账单
*
* @param fileName
*/
private void removeHistoryBill(String fileName, String dirName) throws IOException {
if (!this.payEnvironment.getLaklaBillDownloadPath().exists()) {
try {
try {
Asserts.state(LOCK.tryLock(10, TimeUnit.SECONDS));
} catch (Exception e) {
logger.error("移除存在的账单 - 获取锁失败", e);
}
if (!this.payEnvironment.getLaklaBillDownloadPath().exists()) { //双重验证
boolean flag = this.payEnvironment.getLaklaBillDownloadPath().getFile().mkdirs();
if (!flag) {
throw new IOException("拉卡拉账单-创建目录失败");
}
}
} finally {
LOCK.unlock();
}
}
Resource oldFile = this.payEnvironment.getLaklaBillDownloadPath().createRelative(dirName + "/" + fileName);
if (oldFile.exists()) {
boolean flag = oldFile.getFile().delete();
if (!flag) {
logger.error("拉卡拉账单-历史账单删除失败");
}
}
}
}