Index: pom.xml
===================================================================
--- pom.xml	(revision 28943)
+++ pom.xml	(revision 29042)
@@ -26,10 +26,16 @@
 		<scope>provided</scope>
 	</dependency>
 	<dependency>
-		<groupId>org.springframework.boot</groupId>
-		<artifactId>spring-boot-starter-jta-atomikos</artifactId>
+		<groupId>org.apache.commons</groupId>
+		<artifactId>commons-lang3</artifactId>
+		<version>3.9</version>
 	</dependency>
 	<dependency>
+		<groupId>com.google.code.gson</groupId>
+		<artifactId>gson</artifactId>
+		<version>2.8.5</version>
+	</dependency>
+	<dependency>
 		<groupId>com.alibaba</groupId>
 		<artifactId>fastjson</artifactId>
 		<version>1.2.56</version>
Index: src/main/java/com/novaone/common/CommonInfo.java
===================================================================
--- src/main/java/com/novaone/common/CommonInfo.java	(revision 28943)
+++ src/main/java/com/novaone/common/CommonInfo.java	(revision 29042)
@@ -131,4 +131,42 @@
 
     // 商品类型 冻肉
     public static final String GOODS_TYPE_DY = "C";
+
+    /**
+     * 发送心跳的URL地址
+     */
+    public static final String WECHAT_REFRESHTIME_URL = "http://www.fruitease.com:8009/IFView/PortHandler.ashx?action=wechatRefreshTime&modulecode=ccsehgpdf&token=1";
+
+    /**
+     * 表”certificate_download_info“中的数据状态
+     *     -1：未进行下载操作。
+     *      0：下载失败
+     *      1：上传失败
+     *      2：上传成功
+     *      3：根据报关单号查询到多条业务数据
+     */
+    public static final int CERT_STATE_INITIAL = -1;
+    public static final int CERT_STATE_DOWN_FAIL = 0;
+    public static final int CERT_STATE_UP_FAIL = 1;
+    public static final int CERT_STATE_UP_SUCCESS = 2;
+    public static final int CERT_STATE_REPEAT = 3;
+
+    /**
+     * 表：certificate_retry_job标记是否是合同下载失败任务。
+     *      0：下载成功
+     *      1：下载失败
+     */
+    public static final int JOB_CERT_DOWN_FAIL = 1;
+    public static final int JOB_CERT_DOWN_SUCCESS = 0;
+
+    /**
+     * 表：certificate_retry_job标记是否是合同上传失败任务。
+     *      0：未进行上传操作。
+     *      1：上传失败
+     */
+    public static final int JOB_CERT_UP_UNLOADED = 0;
+    public static final int JOB_CERT_UP_FAIL = 1;
+
+
+
 }
Index: src/main/java/com/novaone/config/MySqlDataSourceConfig.java
===================================================================
--- src/main/java/com/novaone/config/MySqlDataSourceConfig.java	(revision 28943)
+++ src/main/java/com/novaone/config/MySqlDataSourceConfig.java	(revision 29042)
@@ -1,9 +1,6 @@
 package com.novaone.config;
 
 import com.alibaba.druid.pool.DruidDataSource;
-import com.atomikos.jdbc.AtomikosDataSourceBean;
-//import com.mysql.jdbc.jdbc2.optional.MysqlXADataSource;
-import com.mysql.cj.jdbc.MysqlXADataSource;
 import org.apache.ibatis.session.SqlSessionFactory;
 import org.mybatis.spring.SqlSessionFactoryBean;
 import org.mybatis.spring.SqlSessionTemplate;
Index: src/main/java/com/novaone/controller/SmsController.java
===================================================================
--- src/main/java/com/novaone/controller/SmsController.java	(revision 28943)
+++ src/main/java/com/novaone/controller/SmsController.java	(revision 29042)
@@ -1,13 +1,14 @@
 package com.novaone.controller;
 
-import com.alibaba.fastjson.JSON;
 import com.novaone.common.R;
 import com.novaone.entity.SmsInfo;
 import com.novaone.service.QueryCodeService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
-import javax.servlet.http.HttpServletRequest;
+
+import javax.validation.constraints.NotEmpty;
 import java.util.*;
 
 /*
@@ -25,24 +26,28 @@
     private QueryCodeService queryCodeService;
 
     @PostMapping("/add")
-    public R add(@RequestBody SmsInfo smsInfo, HttpServletRequest request){
+    public R add(@RequestBody @Validated SmsInfo smsInfo){
         try {
             queryCodeService.saveQueryCode(smsInfo);
             return R.success();
         } catch (Exception e) {
+            log.error(e.getMessage());
             e.printStackTrace();
-        return R.error(e.getMessage());
+            return R.error(e.getMessage());
         }
     }
 
     @PostMapping("/putList")
-    public R add(@RequestBody Set<SmsInfo> smsSet){
-        if (smsSet == null || smsSet.size() == 0)
-            return R.error("请求数据为空");
+    public R putList(@RequestBody Set<SmsInfo> smsSet){
+        if (smsSet == null || smsSet.isEmpty()) {
+            log.error("APP端推送短信列表为空");
+            return R.error("至少包含一条短信");
+        }
         try {
             queryCodeService.saveList(smsSet);
             return R.success();
         } catch (Exception e) {
+            log.error(e.getMessage());
             e.printStackTrace();
             return R.error(e.getMessage());
         }
Index: src/main/java/com/novaone/entity/BgSyrsz.java
===================================================================
--- src/main/java/com/novaone/entity/BgSyrsz.java	(nonexistent)
+++ src/main/java/com/novaone/entity/BgSyrsz.java	(revision 29042)
@@ -0,0 +1,18 @@
+package com.novaone.entity;
+
+import lombok.Data;
+
+/*
+ * @program: ccsehgpdf
+ * @description: 表：yw_bg_syrsz
+ * @author: Ma.ChengJian
+ * @create: 2021-11-09 13:13
+ */
+@Data
+public class BgSyrsz {
+    private String id;//ID
+    private String bm;//部门
+    private String jcka;//进出口岸
+    private String syrmc;//使用人名称
+    private String syrdh;//使用人电话
+}
Index: src/main/java/com/novaone/entity/CertificateRetryJob.java
===================================================================
--- src/main/java/com/novaone/entity/CertificateRetryJob.java	(revision 28943)
+++ src/main/java/com/novaone/entity/CertificateRetryJob.java	(revision 29042)
@@ -1,6 +1,6 @@
 package com.novaone.entity;
 
-import com.alibaba.fastjson.annotation.JSONField;
+import com.novaone.common.CommonInfo;
 import lombok.Data;
 import java.util.Date;
 
@@ -15,7 +15,6 @@
     private Long id;
     private Long infoId;
     private String queryCode;
-    @JSONField(ordinal = 1)
     private String certificateNo;
     private Integer failDownload;
     private Date downloadTime;
@@ -33,10 +32,10 @@
         job.setCreateTime(new Date());
         job.setUpdateTime(new Date());
         job.setRetryCount(0);
-        job.setFailDownload(1);//下载失败
+        job.setFailDownload(CommonInfo.JOB_CERT_DOWN_FAIL);//下载失败 1
         job.setQueryCode(queryCode);
         job.setCertificateNo(certificateNo);
-        job.setFailUpload(0);//未进行上传操作
+        job.setFailUpload(CommonInfo.JOB_CERT_UP_UNLOADED);//未进行上传操作 0
         job.setYwbh(ywbh);
         job.setMessage(message);
         return job;
@@ -49,10 +48,10 @@
         job.setUpdateTime(new Date());
         job.setDownloadTime(new Date());
         job.setRetryCount(0);
-        job.setFailDownload(0);//下载成功
+        job.setFailDownload(CommonInfo.JOB_CERT_DOWN_SUCCESS);//下载成功 0
         job.setQueryCode(queryCode);
         job.setCertificateNo(certificateNo);
-        job.setFailUpload(1);//上传失败
+        job.setFailUpload(CommonInfo.JOB_CERT_UP_FAIL);//上传失败 1
         job.setYwbh(ywbh);
         job.setMessage(message);
         job.setFilePath(path);//文件存储路径
Index: src/main/java/com/novaone/entity/Hddz.java
===================================================================
--- src/main/java/com/novaone/entity/Hddz.java	(revision 28943)
+++ src/main/java/com/novaone/entity/Hddz.java	(revision 29042)
@@ -15,6 +15,8 @@
     private String jyjyzs;  //上传的文件名称,多个文件名称之间使用 ; 分隔，且第一个文件名称前面也带有 ;
     private String bgdh;//检疫证书对应的报关单号
     private String ywbh;//业务编号
+    private String bm;//部门
+    private String jcka;//进出口岸
 
     public Hddz() {
     }
Index: src/main/java/com/novaone/entity/SmsInfo.java
===================================================================
--- src/main/java/com/novaone/entity/SmsInfo.java	(revision 28943)
+++ src/main/java/com/novaone/entity/SmsInfo.java	(revision 29042)
@@ -4,16 +4,24 @@
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 
+import javax.validation.Valid;
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
 import java.util.Date;
 
 @Data
 public class SmsInfo {
+    @NotNull(message = "id是必须的参数")
     private Long id;                        //短信的ID
     private String address;                  //发送地址
     private int type;                        //类型
+    @NotEmpty(message = "短信内容是必须的参数")
     private String body;                     //短信内容
+    @NotNull(message = "短信日期是必须的参数")
     private Date date;                       //时间
+    @NotEmpty(message = "证书编号是必须的参数")
     private String certificateNo;
+    @NotEmpty(message = "查询码是必须的参数")
     private String queryCode;
 
     public SmsInfo() { }
Index: src/main/java/com/novaone/fdao/BgSyrszDao.java
===================================================================
--- src/main/java/com/novaone/fdao/BgSyrszDao.java	(nonexistent)
+++ src/main/java/com/novaone/fdao/BgSyrszDao.java	(revision 29042)
@@ -0,0 +1,21 @@
+package com.novaone.fdao;
+
+import com.novaone.entity.BgSyrsz;
+
+import java.util.List;
+
+/*
+ * @program: ccsehgpdf
+ * @description: 表：yw_bg_syrsz的读写操作
+ * @author: Ma.ChengJian
+ * @create: 2021-11-09 13:38
+ */
+public interface BgSyrszDao {
+    /**
+     * 根据给定条件查询联系人
+     * @param bm 部门
+     * @param jcka 进出口岸
+     * @return 联系人
+     */
+    List<BgSyrsz> findByCondition(String bm, String jcka);
+}
Index: src/main/java/com/novaone/job/EasipassHeartbeatCron.java
===================================================================
--- src/main/java/com/novaone/job/EasipassHeartbeatCron.java	(revision 28943)
+++ src/main/java/com/novaone/job/EasipassHeartbeatCron.java	(revision 29042)
@@ -1,5 +1,6 @@
 package com.novaone.job;
 
+import com.novaone.common.CommonInfo;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.scheduling.annotation.Scheduled;
@@ -25,16 +26,15 @@
 public class EasipassHeartbeatCron {
     private final Logger log = LoggerFactory.getLogger(this.getClass());
 
-    private static final String WECHAT_REFRESHTIME_URL = "http://www.fruitease.com:8009/IFView/PortHandler.ashx?action=wechatRefreshTime&modulecode=ccsehgpdf&token=1";
-
     // 每10分钟检查一次
     @Scheduled(cron = "0 */10 * * * ?")
     public void core() {
         try {
-            String result = HttpUtil.get(WECHAT_REFRESHTIME_URL);
+            String result = HttpUtil.get(CommonInfo.WECHAT_REFRESHTIME_URL);
             log.info("EasipassHeartbeatCron sendResult: " + result);
         } catch (Exception e) {
             log.error("EasipassHeartbeatCron ERROR:" + e.getMessage(), e);
+            e.printStackTrace();
         }
     }
 }
Index: src/main/java/com/novaone/job/Timer.java
===================================================================
--- src/main/java/com/novaone/job/Timer.java	(revision 28943)
+++ src/main/java/com/novaone/job/Timer.java	(revision 29042)
@@ -8,6 +8,7 @@
 import com.novaone.entity.QueryCodeRetryJob;
 import com.novaone.service.CertificateService;
 import com.novaone.service.QueryCodeService;
+import com.novaone.service.impl.CertificateServiceImpl;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Scheduled;
@@ -38,37 +39,38 @@
     private QueryCodeService queryCodeService;
 
     //每小时整点和半点执行一次。
-    @Scheduled(cron = "0 0/30 * * * *")
+//    @Scheduled(cron = "0 0/30 * * * *")
     public void certificateUpload(){
-        List<CertificateDownloadInfo> list = certificateInfoDao.findByBusinesState(-1);
+        List<CertificateDownloadInfo> list = certificateInfoDao.findByBusinesState(CommonInfo.CERT_STATE_INITIAL);
         log.info("[检疫证书上传任务]本次待下载并上传检疫证书数量:"+list.size());
-        list.parallelStream().forEach(item->certificateService.upload(item));
+        for (CertificateDownloadInfo info : list) {
+            certificateService.upload(info);
+        }
     }
 
     /**
-     * 每小时的25分、40分、55分执行一次。
+     * 每小时的10分、25分、40分、55分执行一次。
      */
-    @Scheduled(cron = "0 10/15 * * * *")
+//    @Scheduled(cron = "0 10/15 * * * *")
     public void retryUpload(){
         List<CertificateRetryJob> retryJob = certificateService.findRetryJob();
-        if (retryJob.size()<1)return;
         log.info("[检疫证书重试任务]本次重试任务数量:{}",retryJob.size());
-        retryJob.stream()
-                .filter(item -> item.getFailDownload() == 1 && item.getFailUpload() == 0).parallel()
-                .forEach((item -> certificateService.retryDownload(item)));
-        retryJob.stream()
-                .filter(str -> str.getFailDownload() == 0 && str.getFailUpload() == 1)
-                .parallel()
-                .forEach((job -> certificateService.retryUpload(job)));
+        for (CertificateRetryJob job : retryJob) {
+            certificateService.retryDownload(job);
+        }
     }
 
-
-    @Scheduled(cron = "0 5/10 * * * *")
+    /**
+     * 每小时的5分、15分
+     */
+//    @Scheduled(cron = "0 5/10 * * * *")
     public void retrySaveQueryCode(){
         List<QueryCodeRetryJob> retryJob = queryCodeService.findAll();
-        if (retryJob.size()<1)return;
+        if (retryJob.isEmpty())return;
         log.info("[查询码写入重试任务]本次重试任务数量:{}",retryJob.size());
-        retryJob.parallelStream().forEach(item -> queryCodeService.retrySave(item));
+        for (QueryCodeRetryJob job : retryJob) {
+            queryCodeService.retrySave(job);
+        }
     }
 
 }
Index: src/main/java/com/novaone/service/CertificateService.java
===================================================================
--- src/main/java/com/novaone/service/CertificateService.java	(revision 28943)
+++ src/main/java/com/novaone/service/CertificateService.java	(revision 29042)
@@ -13,13 +13,7 @@
  */
 public interface CertificateService {
 
-    /**
-     * 重试下载成功但上传失败的任务。
-     * @param job 重试任务
-     */
-    void retryUpload(CertificateRetryJob job);
 
-
     /**
      * 重试下载失败的任务，重新执行下载并上传。
      * @param job
Index: src/main/java/com/novaone/service/SmsService.java
===================================================================
--- src/main/java/com/novaone/service/SmsService.java	(revision 28943)
+++ src/main/java/com/novaone/service/SmsService.java	(revision 29042)
@@ -1,8 +1,11 @@
 package com.novaone.service;
 
 import com.novaone.entity.CertificateDownloadInfo;
+import com.novaone.entity.SmsInfo;
 
+import java.net.URISyntaxException;
 
+
 /*
  * @program: ccsehgpdf
  * @description:
@@ -12,4 +15,7 @@
 public interface SmsService {
     public void save(CertificateDownloadInfo certificateDownloadInfo);
 
+    public void forwardSMS(String ywbh, SmsInfo sms) throws URISyntaxException;
+
+
 }
Index: src/main/java/com/novaone/service/impl/CertificateServiceImpl.java
===================================================================
--- src/main/java/com/novaone/service/impl/CertificateServiceImpl.java	(revision 28943)
+++ src/main/java/com/novaone/service/impl/CertificateServiceImpl.java	(revision 29042)
@@ -2,6 +2,7 @@
 
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
+import com.novaone.common.CommonInfo;
 import com.novaone.dao.CertificateDownloadInfoDao;
 import com.novaone.dao.CertificateRetryJobDao;
 import com.novaone.entity.CertificateDownloadInfo;
@@ -17,10 +18,14 @@
 import org.apache.commons.lang.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.io.*;
 import java.net.HttpURLConnection;
 import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Paths;
 import java.util.*;
 
 
@@ -33,7 +38,7 @@
 @Slf4j
 @Service
 public class CertificateServiceImpl implements CertificateService {
-
+    // todo 文件上传基础路径
     private final String BASE_DIR = "/download_test/";
 //    private final String BASE_DIR = "/wenjian/CIQ TAX/";
 
@@ -49,71 +54,101 @@
      * @param certificate
      */
     @Override
+    @Transactional
     public void upload(CertificateDownloadInfo certificate) {
-        String queryCode = certificate.getQueryCode();
-        Long certificateId = certificate.getId();
         String certificateNo = Optional.of(certificate.getCertificateNo()).orElseThrow(()->new NullPointerException("The certificateNo cannot be Null"));
-        String ywbh = certificate.getYwbh();
-        String fileName = certificateNo+".pdf";
-
-        InputStream inputStream = getFileData(queryCode, certificateNo,5);
-        //查询不到证书列表和下载失败都会返回null
-        if (inputStream == null) {
-            updateCertificateInfo(0,certificateId);
-            addRetryJob(CertificateRetryJob.downloadJob(certificateId, queryCode, certificateNo,ywbh,"证书下载失败"));
+        log.info("[检疫证书上传]开始执行检疫证书下载并上传,CertificateNo:{}",certificateNo);
+        //下载文件，获取文件存储路径。
+        String filePath = null;
+        try {
+            filePath = downLoad(certificate);
+        } catch (IOException e) {
+            //本地存储失败，添加下载重试任务
+            addRetryJob(CertificateRetryJob.downloadJob(certificate.getId(),
+                    certificate.getQueryCode(),
+                    certificate.getCertificateNo(),
+                    certificate.getYwbh(),
+                    "检疫证书本地存储失败;"+e.getMessage()));
+            updateCertificateInfo(CommonInfo.CERT_STATE_DOWN_FAIL,certificate.getId());
+            log.error("[检疫证书下载}本地存储失败,CertificateNo:{}",certificate.getCertificateNo());
+            e.printStackTrace();
             return;
         }
-
-        /**
-         * 打开FTP链接，连接失败重试5次。若无法连接文件将保存至本地。
-         */
-        FtpUtil connect = getConnect(5);
-        if (connect == null) {
-            log.error("[检疫证书上传]失败,FTP服务无法连接...");
-            String path = storage(certificateId, queryCode, certificateNo, ywbh, inputStream);//存储文件并添加下载/上传重试任务
-            if (path == null){
-                updateCertificateInfo(0,certificateId);//下载失败
-            }else {
-                updateCertificateInfo(1,certificateId);//上传失败
+        if (filePath == null) return;
+        //文件上传，上传失败添加重试任务
+        File file = new File(filePath);
+        if (!uploadFile(certificate, file)){
+            if (file.exists() && !file.delete()) {
+                log.error("本地文件删除失败,文件路径:{}",file.getAbsolutePath());
             }
-          return;
+            return;
         }
-
-        /**
-         * 上传下载的检疫证书
-         * http://www.fruitease.com:8009/wenjian/CIQ TAX/310040115012788.pdf
-         */
-        HashMap<String, InputStream> ftpFile = new HashMap<>();
-        ftpFile.put(BASE_DIR+ fileName , inputStream);
-        if (connect.upload(ftpFile)) {
-            Hddz hddz = new Hddz();
-            hddz.setBgdh(certificateNo.substring(0, certificateNo.length() - 3));
-            hddz.setSfyjyjyzs("Y");
-            hddz.setJyjyzs(fileName);
-            hddz.setYwbh(certificate.getYwbh());
-            hddzService.uploadSuccessful(hddz);//todo 更新水果通两张表
-            updateCertificateInfo(2, certificateId);//证书上传成功
-            log.info("[检疫证书上传成功],certificateInfo{}",JSON.toJSONString(certificate));
-
-        }else {
-            log.error("[检疫证书上传失败]FTP上传操作不成功,certificateInfo{}",JSON.toJSONString(certificate));
-            storage(certificateId, queryCode, certificateNo, ywbh, inputStream);//存储文件并添加下载重试任务
+        if (!file.delete()) {
+            log.error("成功上传的证书文件没有从本地被删除,文件路径:{}",file.getAbsolutePath());
         }
-        connect.disConnect();
+        Hddz hddz = new Hddz();
+        hddz.setBgdh(certificateNo.substring(0, certificateNo.length() - 3));
+        hddz.setSfyjyjyzs("Y");
+        hddz.setJyjyzs(certificateNo+".pdf");
+        hddz.setYwbh(certificate.getYwbh());
+        hddzService.uploadSuccessful(hddz);//todo 更新水果通两张表
+        updateCertificateInfo(CommonInfo.CERT_STATE_UP_SUCCESS, certificate.getId());//证书上传成功
+        log.info("[检疫证书上传]检疫证书上传成功,CertificateNo:{}", certificateNo);
     }
 
-    @Override
-    public void addRetryJob(CertificateRetryJob retryJob) {
-        retryJobDao.add(retryJob);
-        log.info("[添加合同重试任务]certificateRetryJob = "+ JSON.toJSONString(retryJob));
-    }
 
+
+    /**
+     * 重试下载并上传
+     * @param job 重试任务
+     */
     @Override
-    public List<CertificateRetryJob> findRetryJob() {
-        return retryJobDao.findRetryJob();
+    @Transactional
+    public void retryDownload(CertificateRetryJob job) {
+        log.info("[检疫证书重试上传]开始执行检疫证书重试下载并上传,CertificateNo:{}",job.getCertificateNo());
+        String certificateNo = Optional.of(job.getCertificateNo()).orElseThrow(()->new NullPointerException("The certificateNo cannot be Null"));
+        String fileName = certificateNo+".pdf";
+        String filePath = null;
+        try {
+            //下载证书文件到本地
+            filePath = downLoad(job);
+        } catch (IOException e) {
+            updateRetryJob(job,"检疫证书本地存储失败;"+e.getMessage());
+            log.error("[检疫证书重试上传}本地存储失败,CertificateNo:{}",job.getCertificateNo());
+            return;
+        }
+        if (filePath == null) return;
+        File file = new File(filePath);
+        //上传证书文件到水果通
+        if (!uploadFile(job, file)){
+            if (file.exists() && !file.delete()) {
+                log.error("本地文件删除失败,文件路径:{}",file.getAbsolutePath());
+            }
+            return;
+        }
+        if (!file.delete()) {
+            log.error("成功上传的证书文件没有从本地被删除,文件路径:{}",file.getAbsolutePath());
+        }
+        //更新SqlServer和MySQL中的数据。
+        Hddz hddz = new Hddz();
+        hddz.setBgdh(certificateNo.substring(0, certificateNo.length() - 3));
+        hddz.setSfyjyjyzs("Y");
+        hddz.setJyjyzs(fileName);//证书名称
+        hddz.setYwbh(job.getYwbh());
+        hddzService.uploadSuccessful(hddz);//todo 更新水果通两张表
+        retryJobDao.deleteById(job);
+        updateCertificateInfo(CommonInfo.CERT_STATE_UP_SUCCESS,job.getInfoId());//证书上传成功 2
+        updateRetryJob(job,"FTP上传操作不成功");
     }
 
+
+    /**
+     * 更新重试任务
+     * @param job 任务
+     * @param message 任务描述
+     */
     @Override
+    @Transactional
     public void updateRetryJob(CertificateRetryJob job, String message) {
         job.setMessage(message);
         job.setRetryCount(Optional.ofNullable(job.getRetryCount()).orElse(0)+1);
@@ -123,159 +158,159 @@
 
 
     /**
-     * 重试下载成功，但上传失败的任务
-     * @param job 重试任务
+     * 查询全部重试任务
+     * @return 任务列表
      */
     @Override
-    public void retryUpload(CertificateRetryJob job) {
-        FtpUtil connect = getConnect(5);
-        String fileName = Optional.of(job.getCertificateNo()).orElseThrow(() -> new NullPointerException("The certificateNo cannot be Null"))+".pdf";
-        if (connect == null) {
-            log.error("[检疫证书上传重试]FTP服务无法连接,重试失败...");
-            updateRetryJob(job,"FTPl连接获取失败");
-            return;
-        }
-        FileInputStream fileInputStream = null;
-        try {
-            fileInputStream = new FileInputStream(new File(job.getFilePath()));
-        } catch (FileNotFoundException e) {
-            log.error("[检疫证书上传重试]检疫证书文件不存在,文件路径{}",job.getFilePath());
-            e.printStackTrace();
-            job.setFailDownload(1);//修改任务为下载重试任务
-            job.setFailUpload(0);//上传状态
-            job.setRetryCount(0);
-            updateRetryJob(job,"本地文件不存在,路径="+job.getFilePath());
-            return;
-        }
-        Map<String,InputStream> param = new HashMap<>();
-        param.put(BASE_DIR+ fileName,fileInputStream);
-        if (connect.upload(param)) {
-            Hddz hddz = new Hddz();
-            hddz.setBgdh(job.getCertificateNo().substring(0, job.getCertificateNo().length() - 3));
-            hddz.setSfyjyjyzs("Y");
-            hddz.setJyjyzs(fileName);
-            hddz.setYwbh(job.getYwbh());
-           hddzService.uploadSuccessful(hddz);// todo 更新水果通两张表
-            log.info("[检疫证书上传重试]成功,job = {}",JSON.toJSONString(job));
-            retryJobDao.deleteById(job);
-            updateCertificateInfo(2,job.getInfoId());
-            try {
-                fileInputStream.close();
-                if (new File(job.getFilePath().replaceAll("\\\\", "\\\\\\\\")).delete()) {
-                    log.info("[检疫证书上传重试]删除本地证书文件{},",job.getFilePath());
-                }
-            } catch (IOException e) {
-                e.printStackTrace();
-            }
-            return;
-        }
-        log.error("[检疫证书上传重试]失败,FTP上传操作不成功 job = {}",JSON.toJSONString(job));
-        job.setRetryCount(Optional.ofNullable(job.getRetryCount()).orElse(0)+1);
-        updateRetryJob(job,"FTP上传操作不成功");
+    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
+    public List<CertificateRetryJob> findRetryJob() {
+        return retryJobDao.findRetryJob();
     }
 
+
     /**
-     * 重试下载并上传
-     * @param job 重试任务
+     * 新增一条重试任务
+     * @param retryJob 任务
      */
     @Override
-    public void retryDownload(CertificateRetryJob job) {
-        log.info("开始任务 = {}",JSON.toJSONString(job));
-        String certificateNo = Optional.of(job.getCertificateNo()).orElseThrow(()->new NullPointerException("The certificateNo cannot be Null"));
-        String queryCode = job.getQueryCode();
-        String fileName = certificateNo+".pdf";
-        InputStream fileData = getFileData(queryCode, certificateNo, 3);
-        if (fileData == null){
-            log.info("[检疫证书下载重试]失败");
-            updateRetryJob(job,"证书下载失败");
-            return;
+    @Transactional
+    public void addRetryJob(CertificateRetryJob retryJob) {
+        retryJobDao.add(retryJob);
+        log.info("[添加合同重试任务]certificateRetryJob = "+ JSON.toJSONString(retryJob));
+    }
+
+
+
+    /**
+     * 根据列表查询结果，解析出文件加载的必要参数组装下载链接。
+     * @param searchResult 列表查询结果
+     * @return 检疫证书文件下载链接
+     */
+    private String getDownUrlBySearchResult(String searchResult) {
+        String certNo = RegexUtil.matchOne("(?<=\"certNo\":\")(.*?)(?=\\\")", searchResult);
+        String certFileSeqNo = RegexUtil.matchOne("(?<=\"certFileSeqNo\":\")(.*?)(?=\\\")", searchResult);
+        String serialNo = RegexUtil.matchOne("(?<=\"serialNo\":\")(.*?)(?=\\\")", searchResult);
+        String seqNo = RegexUtil.matchOne("(?<=\"seqNo\":\")(.*?)(?=\\\")", searchResult);
+        String downUrl = "https://swapp.singlewindow.cn/ecertwebunloginserver/sw/ecert/unlogin/downloadPDF/" + certNo + "/" + certFileSeqNo + "/" + serialNo + "/6" + "/" + seqNo;
+        if (certNo == null || certFileSeqNo == null || serialNo == null || seqNo == null){
+            log.error("[检疫证书查询]未能从列表查询结果中解析出必要的参数。DownLoadUrl = {}",downUrl);
         }
-        FtpUtil connect = getConnect(3);
-        if (connect == null) {
-            log.error("[检疫证书下载重试]FTP服务无法连接,重试失败...");
-            updateRetryJob(job,"FTP服务器连接失败");
-            return;
-        }
+        return downUrl;
+    }
 
-        HashMap<String, InputStream> ftpFile = new HashMap<>();
-        ftpFile.put(BASE_DIR+ fileName, fileData);
-        if (connect.upload(ftpFile)) {
-            Hddz hddz = new Hddz();
-            hddz.setBgdh(certificateNo.substring(0, certificateNo.length() - 3));
-            hddz.setSfyjyjyzs("Y");
-            hddz.setJyjyzs(fileName);//证书名称
-            hddz.setYwbh(job.getYwbh());
-            hddzService.uploadSuccessful(hddz);//todo 更新水果通两张表
-            retryJobDao.deleteById(job);
-            updateCertificateInfo(2,job.getInfoId());
-            return;
+
+
+    /**
+     * 根据证书号和查询码，查询检疫证书列表。查询不到检疫证书则添加下载重试任务。
+     * @param info 合同下载需要的信息
+     * @param retryCount 验证码错误的重试次数
+     * @return 列表查询结果的JSON串，失败返回null
+     */
+    private String getSearchResult(CertificateDownloadInfo info, int retryCount) {
+        String searchResult;
+        String message;
+        do {
+            HashMap<String, String> param = CertificateUtils.downloadImg(3);
+            //{"total":0,"rows":[]}
+            //{"message":"验证码不正确！","total":0,"rows":[]}
+            //{"total":1,"rows":[{"queryType":null,"chgNo":null,"reportDateEnd":null,"remark":null,"processStatus":"0","seqNo":"202100000004252635","qrFileSeqNo":"202110147029876214671300496101","assessDeptCode":null,"certSource":"C","drawOrgCode":"2225","signDate":null,"certDate":null,"qrFilePath":"/swgpfs/ecert/2021/10/14/09/28/1300496/58/202110147029876214671300496101.PNG","orgCode":"310000","checkDate":null,"makerCode":null,"entMgrNo":null,"stName":null,"collecterCode":null,"coaDeclNo":null,"assessOrgCode":null,"declNo":"222520211000253049","reportStatus":"0","interpretDate":null,"validState":"1","addNo":null,"changeType":"0","makeDate":null,"formatId":null,"interpreter":null,"printOriginalNum":null,"printDuplicateNum":null,"declTypeCode":"I","checkOperatorCode":null,"releaserCode":null,"oldCertNo":null,"declDate":null,"language":"12","phaseStatus":"4","indbTime":"2021-10-14 09:28:04","certFilePath":"/swgpfs/ecert/2021/10/14/09/28/1300496/73/202110142686751893051300496109.pdf","processId":"9a1b7bf0a73742e8bee749458eed5266","stOrder":null,"backReason":null,"reviewOperatorCode":null,"drawDate":null,"id":"5e634b72dd8747089622d0cff13a6d1d","storeModeCode":null,"extendNo":0,"releaseDate":null,"certFileSeqNo":"202110142686751893051300496109","transBatch":"20211014092717839","ccsReportDate":null,"formatNo":"2501","handoverDate":null,"signerCode":null,"drawerCode":null,"entOrgCode":null,"reportDate":"2021-10-14 09:27:17","cusRegNo":null,"drawDeptCode":null,"submitProcessId":null,"end":0,"validStateName":"有效","assessorCode":null,"qrValid":"1","transFlag":null,"reviewDate":null,"ccsReportStatus":"E","repNo":null,"handoverCode":null,"partiNo":null,"collectDate":null,"begin":0,"serialNo":"1901","formatNoName":" 5-1入境货物检验检疫证明","useState":null,"formatVersion":"1.0","certNo":"222520211000253049001","originDeclNo":null,"deptCode":null,"assessDate":null,"destCountry":null}]}
+            searchResult = Optional.ofNullable(CertificateUtils.listPage(param.get("code"), param.get("cookie"), info.getQueryCode(), info.getCertificateNo())).orElse("{}");
+            JSONObject resultObject = JSON.parseObject(searchResult);
+            message = resultObject.getString("message");
+            if (!StringUtils.isEmpty(message) && message.contains("验证码不正确")) {
+                log.info("[检疫证书查询]列表查询失败,验证码错误。");
+                continue;
+            }
+            if (resultObject.getJSONArray("rows").isEmpty()) {
+                log.error("[检疫证书查询]未查询到检疫证书,CertificateNo = {}", info.getCertificateNo());
+                // todo 检疫证书查询不到，添加下载重试任务
+                addRetryJob(CertificateRetryJob.downloadJob(info.getId(), info.getQueryCode(), info.getCertificateNo(), info.getYwbh(),"根据证书编号和查询码未查询到检疫证书"));
+                updateCertificateInfo(CommonInfo.CERT_STATE_DOWN_FAIL,info.getId());
+                return null;
+            }
+            break;
+        }while (--retryCount > 0);
+        if (message != null && message.contains("验证码不正确") ) {
+            //todo 检疫证书下载失败，列表查询验证码错误。添加重试任务
+            addRetryJob(CertificateRetryJob.downloadJob(info.getId(), info.getQueryCode(), info.getCertificateNo(), info.getYwbh(),"检疫证书查询失败,验证码错误"));
+            updateCertificateInfo(CommonInfo.CERT_STATE_DOWN_FAIL,info.getId());
+            return null;
         }
-        updateRetryJob(job,"FTP上传操作不成功");
+        return searchResult;
     }
 
+
     /**
-     * 访问证书下载链接
+     * 处理下载重试任务，根据查询码和证书编号查询证书列表，查询不到更新重试任务。
+     * @param job 重试任务
+     * @param retryCount 验证码错误重试次数
+     * @return 列表查询结果
      */
-    private InputStream getFileData(String queryCode, String certificateNo, int retryCount) {
+    private String getSearchResult(CertificateRetryJob job, int retryCount) {
         String searchResult;
+        String message;
         do {
             HashMap<String, String> param = CertificateUtils.downloadImg(3);
             //{"total":0,"rows":[]}
             //{"message":"验证码不正确！","total":0,"rows":[]}
             //{"total":1,"rows":[{"queryType":null,"chgNo":null,"reportDateEnd":null,"remark":null,"processStatus":"0","seqNo":"202100000004252635","qrFileSeqNo":"202110147029876214671300496101","assessDeptCode":null,"certSource":"C","drawOrgCode":"2225","signDate":null,"certDate":null,"qrFilePath":"/swgpfs/ecert/2021/10/14/09/28/1300496/58/202110147029876214671300496101.PNG","orgCode":"310000","checkDate":null,"makerCode":null,"entMgrNo":null,"stName":null,"collecterCode":null,"coaDeclNo":null,"assessOrgCode":null,"declNo":"222520211000253049","reportStatus":"0","interpretDate":null,"validState":"1","addNo":null,"changeType":"0","makeDate":null,"formatId":null,"interpreter":null,"printOriginalNum":null,"printDuplicateNum":null,"declTypeCode":"I","checkOperatorCode":null,"releaserCode":null,"oldCertNo":null,"declDate":null,"language":"12","phaseStatus":"4","indbTime":"2021-10-14 09:28:04","certFilePath":"/swgpfs/ecert/2021/10/14/09/28/1300496/73/202110142686751893051300496109.pdf","processId":"9a1b7bf0a73742e8bee749458eed5266","stOrder":null,"backReason":null,"reviewOperatorCode":null,"drawDate":null,"id":"5e634b72dd8747089622d0cff13a6d1d","storeModeCode":null,"extendNo":0,"releaseDate":null,"certFileSeqNo":"202110142686751893051300496109","transBatch":"20211014092717839","ccsReportDate":null,"formatNo":"2501","handoverDate":null,"signerCode":null,"drawerCode":null,"entOrgCode":null,"reportDate":"2021-10-14 09:27:17","cusRegNo":null,"drawDeptCode":null,"submitProcessId":null,"end":0,"validStateName":"有效","assessorCode":null,"qrValid":"1","transFlag":null,"reviewDate":null,"ccsReportStatus":"E","repNo":null,"handoverCode":null,"partiNo":null,"collectDate":null,"begin":0,"serialNo":"1901","formatNoName":" 5-1入境货物检验检疫证明","useState":null,"formatVersion":"1.0","certNo":"222520211000253049001","originDeclNo":null,"deptCode":null,"assessDate":null,"destCountry":null}]}
-            searchResult = CertificateUtils.listPage(param.get("code"), param.get("cookie"), queryCode,certificateNo);
+            searchResult = Optional.ofNullable(CertificateUtils.listPage(param.get("code"), param.get("cookie"), job.getQueryCode(), job.getCertificateNo())).orElse("{}");
             JSONObject resultObject = JSON.parseObject(searchResult);
-            String message = resultObject.getString("message");
+            message = resultObject.getString("message");
             if (!StringUtils.isEmpty(message) && message.contains("验证码不正确")) {
-                log.info("[检疫证书查询]失败,验证码错误...");
+                log.info("[检疫证书查询]列表查询失败,验证码错误。");
                 continue;
             }
-            if (resultObject.getJSONArray("rows").size() < 1) {
-                log.info("[检疫证书查询]未查询到检疫证书,certificateNo = {}",certificateNo);
+            if (resultObject.getJSONArray("rows").isEmpty()) {
+                log.error("[检疫证书查询]未查询到检疫证书,CertificateNo = {}", job.getCertificateNo());
+                updateRetryJob(job,"根据证书编号和查询码未查询到检疫证书");
                 return null;
             }
             break;
         }while (--retryCount > 0);
-        String certNo = RegexUtil.matchOne("(?<=\"certNo\":\")(.*?)(?=\\\")", searchResult);
-        String certFileSeqNo = RegexUtil.matchOne("(?<=\"certFileSeqNo\":\")(.*?)(?=\\\")", searchResult);
-        String serialNo = RegexUtil.matchOne("(?<=\"serialNo\":\")(.*?)(?=\\\")", searchResult);
-        String seqNo = RegexUtil.matchOne("(?<=\"seqNo\":\")(.*?)(?=\\\")", searchResult);
-        String downUrl = "https://swapp.singlewindow.cn/ecertwebunloginserver/sw/ecert/unlogin/downloadPDF/" + certNo + "/" + certFileSeqNo + "/" + serialNo + "/6" + "/" + seqNo;
-        if (certNo == null || certFileSeqNo == null || serialNo == null || seqNo == null)return null;
-        try {
-            HttpURLConnection connection = (HttpURLConnection)new URL(downUrl).openConnection();
-            if ("application/octet-stream;charset=UTF-8".equals(connection.getContentType()) && connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
-                log.info("[检疫证书查询]证书文件读取成功...");
-                return connection.getInputStream();
-            }
-            JSONObject logObj = new JSONObject();
-            logObj.put("ResponseCode",connection.getResponseCode());
-            logObj.put("ContentType",connection.getContentType());
-            log.info("[检疫证书查询]证书文件读取失败,{}",logObj.toJSONString());
+        if (message != null && message.contains("验证码不正确") ) {
+            updateRetryJob(job,"检疫证书查询失败,验证码错误");
             return null;
-        } catch (IOException e) {
-            log.error("[检疫证书查询]下载链接请求异常,URL{}",downUrl);
-            e.printStackTrace();
-            return null;
         }
+        return searchResult;
     }
 
-    private String storage(long certificateId, String queryCode, String certificateNo, String ywbh, InputStream inputStream) {
-        File file = new File(certificateNo + ".pdf");
+
+    /**
+     * 下载证书文件到本地
+     * @param bo 合同下载必要的信息或者重试任务
+     * @return 文件存储路径
+     * @throws IOException 文件存储失败
+     */
+    private String downLoad(Object bo) throws IOException {
+        InputStream fileStream = null;
+        String fileName = null;
+        if (bo instanceof CertificateDownloadInfo){
+            fileStream = getFileStream((CertificateDownloadInfo)bo);
+            fileName = ((CertificateDownloadInfo)bo).getCertificateNo();
+        }else if (bo instanceof CertificateRetryJob){
+            fileStream = getFileStream((CertificateRetryJob)bo);
+            fileName = ((CertificateRetryJob) bo).getCertificateNo();
+        }else {
+            throw new IllegalArgumentException("非法的参数类型");
+        }
+        if (fileStream == null)return null;
+        File file = new File(fileName + ".pdf");
         String path = file.getAbsolutePath();
         try {
-            FileUtils.copyToFile(inputStream,file);
-            addRetryJob(CertificateRetryJob.uploadJob(certificateId, queryCode,certificateNo,path,ywbh,"上传至水果通失败"));
-            log.info("[检疫证书下载}本地存储成功,文件路径{}",path);
-            return path;
-        } catch (IOException e) {
-            //本地存储失败，添加下载重试任务
-            addRetryJob(CertificateRetryJob.downloadJob(certificateId, queryCode,certificateNo,ywbh,"检疫证书本地存储失败"));
-            e.printStackTrace();
+            FileUtils.copyToFile(fileStream,file);
+        } finally {
+            fileStream.close();
         }
-        return null;
+        log.info("[检疫证书下载}本地存储成功,文件路径{}",path);
+
+        return path;
     }
 
+
+    /**
+     * 获取HTTP连接
+     */
     private FtpUtil getConnect(int count) {
         FtpUtil ftpUtil = new FtpUtil();
         boolean connect = false;
@@ -296,6 +331,71 @@
         return null;
     }
 
+
+
+    private InputStream getFileStream(CertificateDownloadInfo certificate) {
+        //列表查询检疫证书。如果没有列表查询结果，重试任务在列表查询方法中添加
+        String searchResult = getSearchResult(certificate, 4);
+        if (searchResult == null)return null;
+        //解析列表查询结果，组装证书文件的下载URL
+        String downUrl = getDownUrlBySearchResult(searchResult);
+        try {
+            HttpURLConnection connection = (HttpURLConnection)new URL(downUrl).openConnection();
+            if ("application/octet-stream;charset=UTF-8".equals(connection.getContentType()) && connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
+                log.info("[检疫证书查询]证书文件读取成功。");
+                return connection.getInputStream();
+            }
+            JSONObject logObj = new JSONObject();
+            logObj.put("ResponseCode",connection.getResponseCode());
+            logObj.put("ResponseMessage",connection.getResponseMessage());
+            logObj.put("ContentType",connection.getContentType());
+            log.error("[检疫证书查询]证书文件读取失败,接口响应信息:{}",logObj.toJSONString());
+            addRetryJob(CertificateRetryJob.downloadJob(certificate.getId(),certificate.getQueryCode(), certificate.getCertificateNo(), certificate.getYwbh(),
+                    "证书下载请求响应异常,接口响应信息:"+logObj.toJSONString()));
+            return null;
+        } catch (IOException e) {
+            log.error("[检疫证书查询]下载链接请求异常,DownLoadUrl = {}",downUrl);
+            e.printStackTrace();
+            addRetryJob(CertificateRetryJob.downloadJob(certificate.getId(),certificate.getQueryCode(), certificate.getCertificateNo(), certificate.getYwbh(),
+                    "下载链接请求异常,DownLoadUrl = {}"+downUrl));
+            return null;
+        }
+    }
+
+
+
+    private InputStream getFileStream(CertificateRetryJob job) {
+        String searchResult = getSearchResult(job, 4);
+        //如果没有列表查询结果，重试任务在列表查询方法中添加
+        if (searchResult == null)return null;
+        String downUrl = getDownUrlBySearchResult(searchResult);
+        try {
+            HttpURLConnection connection = (HttpURLConnection)new URL(downUrl).openConnection();
+            if ("application/octet-stream;charset=UTF-8".equals(connection.getContentType()) && connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
+                log.info("[检疫证书查询]证书文件读取成功。");
+                return connection.getInputStream();
+            }
+            JSONObject logObj = new JSONObject();
+            logObj.put("ResponseCode",connection.getResponseCode());
+            logObj.put("ResponseMessage",connection.getResponseMessage());
+            logObj.put("ContentType",connection.getContentType());
+            log.error("[检疫证书查询]证书文件读取失败,{}",logObj.toJSONString());
+            updateRetryJob(job,"证书下载请求响应异常"+logObj.toJSONString());
+            return null;
+        } catch (IOException e) {
+            log.error("[检疫证书查询]下载链接请求异常,DownLoadUrl = {}",downUrl);
+            e.printStackTrace();
+            updateRetryJob(job,"下载链接请求异常,DownLoadUrl = {}"+downUrl);
+            return null;
+        }
+    }
+
+
+
+    /**
+     * 更新certificate_download_info表中的业务数据状态字段
+     * @param businessState 状态值
+     */
     private void updateCertificateInfo(int businessState,Long infoId) {
         CertificateDownloadInfo info = new CertificateDownloadInfo();
         info.setBusinessState(businessState);
@@ -304,5 +404,106 @@
         certificateInfoDao.updateById(info);
     }
 
+
+
+    /**
+     * 上传本地文件
+     * @param file 上传的文件对象
+     */
+    private boolean uploadFile(CertificateDownloadInfo bo, File file) {
+        String certificateNo = Optional.of(bo.getCertificateNo()).orElseThrow(()->new NullPointerException("The certificateNo cannot be Null"));
+        String fileName = certificateNo + ".pdf";
+        Long certificateId = bo.getId();
+        String queryCode = bo.getQueryCode();
+        String ywbh = bo.getYwbh();
+        FileInputStream in = null;
+        try {
+            in = new FileInputStream(file);
+        } catch (FileNotFoundException e) {
+            log.error("[检疫证书上传]证书文件不存在,上传失败。CertificateNo:{},文件路径:{}", certificateNo, file.getAbsolutePath());
+            e.printStackTrace();
+            addRetryJob(CertificateRetryJob.downloadJob(certificateId, queryCode, certificateNo, ywbh, "读取本地证书文件失败,找不到本地证书文件"));
+            updateCertificateInfo(CommonInfo.CERT_STATE_DOWN_FAIL,bo.getId());
+            return false;
+        }
+        FtpUtil connect = getConnect(5);
+        if (connect == null) {
+            log.error("[检疫证书上传]失败,FTP服务无法连接...");
+            addRetryJob(CertificateRetryJob.downloadJob(certificateId, queryCode, certificateNo, ywbh, "获取FTP连接失败"));
+            updateCertificateInfo(CommonInfo.CERT_STATE_DOWN_FAIL,bo.getId());
+            try {
+                in.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+            return false;
+        }
+        /**
+         * 上传下载的检疫证书
+         * http://www.fruitease.com:8009/wenjian/CIQ TAX/310040115012788.pdf
+         */
+        HashMap<String, InputStream> ftpFile = new HashMap<>();
+        ftpFile.put(BASE_DIR + fileName, in);
+        boolean flag = connect.upload(ftpFile);
+        if (!flag){
+            log.error("[检疫证书上传失败]FTP上传操作不成功,CertificateNo:{}", certificateNo);
+            addRetryJob(CertificateRetryJob.downloadJob(certificateId, queryCode, certificateNo, ywbh,"FTP上传操作失败"));
+        }
+        try {
+            in.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        connect.disConnect();
+        return flag;
+    }
+
+
+    /**
+     * 上传文件，针对执行的重试任务。
+     * @param bo 证书重试任务
+     */
+    private boolean uploadFile(CertificateRetryJob bo, File file){
+        String certificateNo = Optional.of(bo.getCertificateNo()).orElseThrow(()->new NullPointerException("The certificateNo cannot be Null"));
+        String fileName = certificateNo + ".pdf";
+        FileInputStream in = null;
+        try {
+            in = new FileInputStream(file);
+        } catch (FileNotFoundException e) {
+            log.error("[检疫证书上传重试]证书文件不存在,上传失败。CertificateNo:{},文件路径:{}", certificateNo, file.getAbsolutePath());
+            e.printStackTrace();
+            updateRetryJob(bo,"读取本地证书文件失败,找不到本地证书文件");
+            return false;
+        }
+        FtpUtil connect = getConnect(5);
+        if (connect == null) {
+            log.error("[检疫证书上传重试]失败,FTP服务无法连接...");
+            updateRetryJob(bo,"获取FTP连接失败");
+            try {
+                in.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+            return false;
+        }
+        /**
+         * 上传下载的检疫证书
+         * http://www.fruitease.com:8009/wenjian/CIQ TAX/310040115012788.pdf
+         */
+        HashMap<String, InputStream> ftpFile = new HashMap<>();
+        ftpFile.put(BASE_DIR + fileName, in);
+        boolean flag = connect.upload(ftpFile);
+        if (!flag){
+            log.error("[检疫证书重试上传]FTP上传操作不成功,CertificateNo:{}", certificateNo);
+            updateRetryJob(bo,"FTP上传操作失败");
+        }
+        try {
+            in.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        connect.disConnect();
+        return flag;
+    }
 }
 
Index: src/main/java/com/novaone/service/impl/HddzServiceImpl.java
===================================================================
--- src/main/java/com/novaone/service/impl/HddzServiceImpl.java	(revision 28943)
+++ src/main/java/com/novaone/service/impl/HddzServiceImpl.java	(revision 29042)
@@ -12,6 +12,7 @@
 import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.List;
 
@@ -25,6 +26,7 @@
 @Service
 public class HddzServiceImpl implements HddzService {
 
+    // todo 文件访问基础路径
     private final String BASE_PATH = "http://www.fruitease.com:8009/wenjian/CIQ TAX/";
 
     @Autowired
@@ -34,6 +36,7 @@
 
 
     @Override
+    @Transactional
     public void addQueryCode(Hddz hddz) {
         hddzDao.update(hddz);
     }
@@ -49,16 +52,23 @@
         hddzOcrwjsb.setSfcz("Y");
         hddzOcrwjsb.setWjlj(BASE_PATH+fileName);//FTP服务的文件访问路径
         hddzDao.update(hddz);
-        hddzOcrwjsbDao.add(hddzOcrwjsb);
+        try {
+            // todo 向hddzOcrwjs表中插入数据，该表不中不能出现重复值。
+            hddzOcrwjsbDao.add(hddzOcrwjsb);
+        } catch (Exception e) {
+            System.err.println("["+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+"]----- 再向表中写入数据时异常了 ----- message："+e.getMessage()+" 报关单号："+hddz.getBgdh());
+        }
         log.info("---文件上传--- SqlServer数据回写成功,hddz = "+ JSON.toJSONString(hddz)+" hddzOcrwjsb = "+JSON.toJSONString(hddzOcrwjsb));
     }
 
     @Override
+    @Transactional
     public void uploadSuccessful(Hddz hddz) {
         this.uploadSuccessful(hddz,hddz.getJyjyzs());
     }
 
     @Override
+    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
     public List<Hddz> findByBgdh(String bgdh) {
         return hddzDao.findByBgdh(bgdh);
     }
Index: src/main/java/com/novaone/service/impl/QueryCodeServiceImpl.java
===================================================================
--- src/main/java/com/novaone/service/impl/QueryCodeServiceImpl.java	(revision 28943)
+++ src/main/java/com/novaone/service/impl/QueryCodeServiceImpl.java	(revision 29042)
@@ -1,6 +1,7 @@
 package com.novaone.service.impl;
 
 import com.alibaba.fastjson.JSON;
+import com.novaone.common.CommonInfo;
 import com.novaone.dao.CertificateDownloadInfoDao;
 import com.novaone.dao.QueryCodeJobDao;
 import com.novaone.entity.CertificateDownloadInfo;
@@ -13,6 +14,7 @@
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.text.SimpleDateFormat;
@@ -53,15 +55,19 @@
             if (hddzList.size() > 1) {
                 byBgdh = new Hddz();
                 certificateInfo.setYwbh("bgdh重复");
-                certificateInfo.setBusinessState(3);
+                certificateInfo.setBusinessState(CommonInfo.CERT_STATE_REPEAT);//重复，状态3
                 log.error("[查询码写入]存在报关单号重复的数据,bgdh={},查询到{}条数据",bgdh,hddzList.size());
-            }else {
+            }else if (hddzList.isEmpty()){
+                log.error("[查询码写入]根据报关单号{},在水果通中未查询到任何数据。",bgdh);
+                return;
+            } else {
                 byBgdh = hddzList.get(0);
                 byBgdh.setJyjyzscxm(queryCode);
                 byBgdh.setBgdh(bgdh);
                 hddzService.addQueryCode(byBgdh);
+                smsService.forwardSMS(byBgdh.getYwbh(),smsInfo);
                 certificateInfo.setYwbh(byBgdh.getYwbh());
-                certificateInfo.setBusinessState(-1);
+                certificateInfo.setBusinessState(CommonInfo.CERT_STATE_INITIAL);//写入成功-1
             }
         } catch (Exception e) {
             log.error("[查询码写入]数据库写入失败,hddz={}",JSON.toJSONString(byBgdh));
@@ -107,22 +113,25 @@
             List<Hddz> list = hddzService.findByBgdh(bgdh);
             if (list.size() > 1) {
                 byBgdh = new Hddz();
-                byBgdh.setBgdh("存在重复");
-                Info.setBusinessState(3);
+                Info.setYwbh("存在重复");
+                Info.setBusinessState(CommonInfo.CERT_STATE_REPEAT);//合同重复状态3
                 log.error("[查询码写入重试]存在报关单号重复的数据,bgdh{}查询到{}条数据",bgdh,list.size());
-            }else {
+            }else if (list.isEmpty()){
+                log.error("[查询码写入重试]根据报关单号{},在水果通中未查询到任何数据。",bgdh);
+                updateJob(job,"根据报关单号不能再水果通中查询到数据,bgdh="+bgdh);
+                return;
+            } else {
                 byBgdh = list.get(0);
                 byBgdh.setJyjyzscxm(queryCode);
                 byBgdh.setBgdh(bgdh);
                 hddzService.addQueryCode(byBgdh);
+                Info.setYwbh(byBgdh.getYwbh());
+                Info.setBusinessState(CommonInfo.CERT_STATE_INITIAL);//新写入-1
             }
         } catch (Exception e) {
             log.error("[查询码写入重试]数据库写入失败,hddz{}",JSON.toJSONString(byBgdh));
             e.printStackTrace();
-            job.setMessage(e.getMessage());
-            job.setUpdateTime(new Date());
-            job.setRetryCount(Optional.ofNullable(job.getRetryCount()).orElse(0)+1);
-            queryCodeJobDao.updateById(job);
+            updateJob(job, e.getMessage());
             return;
         }
         Info.setCertificateNo(certificateNo);
@@ -129,8 +138,6 @@
         Info.setQueryCode(queryCode);
         Info.setReceiveTime(receiveTime);
         Info.setSmsId(smsID);
-        Info.setYwbh(byBgdh.getYwbh());
-        Info.setBusinessState(-1);
         Info.setUpdateTime(new Date());
         Info.setCreateTime(new Date());
         smsService.save(Info);
@@ -138,7 +145,15 @@
         queryCodeJobDao.deleteById(job);
     }
 
+    private void updateJob(QueryCodeRetryJob job, String message) {
+        job.setMessage(message);
+        job.setUpdateTime(new Date());
+        job.setRetryCount(Optional.ofNullable(job.getRetryCount()).orElse(0)+1);
+        queryCodeJobDao.updateById(job);
+    }
+
     @Override
+    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
     public List<QueryCodeRetryJob> findAll() {
         return queryCodeJobDao.find();
     }
@@ -145,7 +160,8 @@
 
 
     @Override
-    public void addRetryJob(SmsInfo smsInfo,String message) {
+    @Transactional
+    public void addRetryJob(SmsInfo smsInfo, String message) {
         QueryCodeRetryJob queryCodeRetryJob = new QueryCodeRetryJob();
         queryCodeRetryJob.setQueryCode(smsInfo.getQueryCode());
         queryCodeRetryJob.setCertificateNo(smsInfo.getCertificateNo());
Index: src/main/java/com/novaone/service/impl/SmsServiceImpl.java
===================================================================
--- src/main/java/com/novaone/service/impl/SmsServiceImpl.java	(revision 28943)
+++ src/main/java/com/novaone/service/impl/SmsServiceImpl.java	(revision 29042)
@@ -2,11 +2,19 @@
 
 import com.novaone.dao.CertificateDownloadInfoDao;
 import com.novaone.entity.CertificateDownloadInfo;
+import com.novaone.entity.SmsInfo;
 import com.novaone.service.SmsService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
+import java.io.File;
+import java.io.FilenameFilter;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+
 /*
  * @program: ccsehgpdf
  * @description:
@@ -24,4 +32,14 @@
     public void save(CertificateDownloadInfo certificateDownloadInfo) {
         certificateDownloadInfoDao.add(certificateDownloadInfo);
     }
+
+    @Override
+    @Transactional
+    public void forwardSMS(String ywbh, SmsInfo sms) throws URISyntaxException {
+        /**
+         * 根据业务编号查询业务接单数据，在业务接单数据中有录入人员的部门和进出口岸数据（bm、jcka）。通过bm和jcka在联系人表中匹配到具体的联系人。
+         */
+
+
+    }
 }
Index: src/main/java/com/novaone/util/CertificateUtils.java
===================================================================
--- src/main/java/com/novaone/util/CertificateUtils.java	(revision 28943)
+++ src/main/java/com/novaone/util/CertificateUtils.java	(revision 29042)
@@ -94,8 +94,8 @@
         try {
             String url = CommonInfo.PALTCODE_API_URL;
             String ret = HttpUtil.postJson(url, obj);
-            log.info("plat code result:" + ret);
             JSONObject jsonObject = JSONObject.parseObject(ret);
+            log.info("[检疫证书查询]验证码识别成功:" + ret);
             if (jsonObject.getBoolean("success")) {
                 code = jsonObject.getJSONObject("data").getString("result");
                 return code;
Index: src/main/java/com/novaone/util/HttpUtil.java
===================================================================
--- src/main/java/com/novaone/util/HttpUtil.java	(revision 28943)
+++ src/main/java/com/novaone/util/HttpUtil.java	(revision 29042)
@@ -1,10 +1,10 @@
 package com.novaone.util;
 
-import java.io.BufferedReader;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
+import com.alibaba.fastjson.JSONObject;
+import org.apache.commons.lang.StringUtils;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.*;
 import java.net.HttpURLConnection;
 import java.net.URL;
 import java.net.URLConnection;
@@ -11,12 +11,6 @@
 import java.util.Map;
 import java.util.Map.Entry;
 
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.commons.lang.StringUtils;
-
-import com.alibaba.fastjson.JSONObject;
-
 public class HttpUtil {
 
     // public static final String url =
@@ -37,14 +31,18 @@
 
         // System.out.println(urlConnection.getURL().toString());
 
-        BufferedReader br = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "utf-8")); // 获取输入流
-        String line = null;
-        StringBuilder sb = new StringBuilder();
-        while ((line = br.readLine()) != null) {
-            sb.append(line + "\n");
+        BufferedReader br = null; // 获取输入流
+        StringBuilder sb;
+        try {
+            br = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "utf-8"));
+            String line = null;
+            sb = new StringBuilder();
+            while ((line = br.readLine()) != null) {
+                sb.append(line + "\n");
+            }
+        } finally {
+            if (br != null) br.close();
         }
-        br.close();
-        // System.out.println(sb.toString());
         return sb.toString();
     }
 
@@ -55,16 +53,18 @@
         if (StringUtils.isNotEmpty(cookie)) {
             urlConnection.setRequestProperty("Cookie", cookie);
         }
-
-        // System.out.println(urlConnection.getURL().toString());
-
-        BufferedReader br = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "utf-8")); // 获取输入流
-        String line = null;
-        StringBuilder sb = new StringBuilder();
-        while ((line = br.readLine()) != null) {
-            sb.append(line + "\n");
+        BufferedReader br = null;
+        StringBuilder sb;
+        try {
+            br = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "utf-8"));
+            String line = null;
+            sb = new StringBuilder();
+            while ((line = br.readLine()) != null) {
+                sb.append(line + "\n");
+            }
+        } finally {
+            if (br != null) br.close();
         }
-        br.close();
         // System.out.println(sb.toString());
         return sb.toString();
     }
@@ -91,19 +91,22 @@
         for (Entry<String, String> entry : parameterMap.entrySet()) {
             parameter.append("&" + entry.getKey() + "=" + entry.getValue());
         }
-        OutputStream os = connection.getOutputStream();
-        os.write(parameter.toString().getBytes("UTF-8"));
-        os.close();
-        // System.out.println("parameter: " + parameter.toString());
-        // System.out.print(connection.getInputStream());
-        BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
-        String line = null;
-        StringBuilder sb = new StringBuilder();
-        while ((line = br.readLine()) != null) { // 读取数据
-            sb.append(line + "\n");
+        BufferedReader br = null;
+        StringBuilder sb;
+        OutputStream os = null;
+        try {
+            os = connection.getOutputStream();
+            os.write(parameter.toString().getBytes("UTF-8"));
+            br = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
+            String line = null;
+            sb = new StringBuilder();
+            while ((line = br.readLine()) != null) { // 读取数据
+                sb.append(line + "\n");
+            }
+        } finally {
+            if (br != null) br.close();
+            if (os != null) os.close();
         }
-        br.close();
-        // System.out.println(sb.toString());
         return sb.toString();
     }
 
@@ -110,7 +113,7 @@
     public static String postJson(String url, JSONObject obj) throws IOException {
         URL u;
         HttpURLConnection con;
-        DataOutputStream osw;
+        DataOutputStream osw = null;
         StringBuffer buffer = new StringBuffer();
         u = new URL(url);
         con = (HttpURLConnection) u.openConnection();
@@ -120,15 +123,20 @@
         con.setUseCaches(false);
         con.setInstanceFollowRedirects(true);
         con.setRequestProperty("Content-Type", "application/json");
-        osw = new DataOutputStream(con.getOutputStream());
-        osw.writeBytes(obj.toString());
-        osw.flush();
-        osw.close();
-        BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));
-        String temp;
-        while ((temp = br.readLine()) != null) {
-            buffer.append(temp);
-            buffer.append('\n');
+        BufferedReader br = null;
+        try {
+            osw = new DataOutputStream(con.getOutputStream());
+            osw.writeBytes(obj.toString());
+            osw.flush();
+            br = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));
+            String temp;
+            while ((temp = br.readLine()) != null) {
+                buffer.append(temp);
+                buffer.append('\n');
+            }
+        } finally {
+            if (osw != null) osw.close();
+            if (br !=null) br.close();
         }
         return buffer.toString();
     }
Index: src/main/java/com/novaone/util/JwtUtil.java
===================================================================
--- src/main/java/com/novaone/util/JwtUtil.java	(revision 28943)
+++ src/main/java/com/novaone/util/JwtUtil.java	(revision 29042)
@@ -1,7 +1,9 @@
 package com.novaone.util;
 
 import java.util.Date;
+import java.util.List;
 
+import com.novaone.entity.SmsInfo;
 import io.jsonwebtoken.Claims;
 import io.jsonwebtoken.Jwts;
 import io.jsonwebtoken.SignatureAlgorithm;
@@ -29,6 +31,25 @@
 //        return token;
 //    }
 
+    public static String geneJsonWebToken(SmsInfo sms) {
+
+        String token = Jwts.builder().setSubject(SUBJECT).claim("id", sms.getId())
+                .claim("smsInfo", sms)
+                .setExpiration(new Date(System.currentTimeMillis() + EXPIRE))
+                .signWith(SignatureAlgorithm.HS256, SECRETKEY).compact();
+
+        return token;
+    }
+
+    public static String geneJsonWebToken(List list) {
+
+        String token = Jwts.builder().setSubject(SUBJECT)
+                .claim("smsInfo", list)
+                .setExpiration(new Date(System.currentTimeMillis() + EXPIRE))
+                .signWith(SignatureAlgorithm.HS256, SECRETKEY).compact();
+        return token;
+    }
+
     // 校验 JWT
     public static Claims checkJWT(String token) {
         try {
Index: src/main/java/com/novaone/util/WechatUtil.java
===================================================================
--- src/main/java/com/novaone/util/WechatUtil.java	(nonexistent)
+++ src/main/java/com/novaone/util/WechatUtil.java	(revision 29042)
@@ -0,0 +1,117 @@
+package com.novaone.util;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.lang3.StringUtils;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 
+ *     
+ * 项目名称：foreignprocurement    
+ * 类名称：WechatUtil    
+ * 类描述：    
+ * 创建人：zhaojiyan    
+ * 创建时间：2017年7月25日 下午2:57:56    
+ * 修改人：zhaojiyan    
+ * 修改时间：2017年7月25日 下午2:57:56    
+ * 修改备注：    
+ * @version     
+ *
+ */
+@Slf4j
+public class WechatUtil {
+
+    private WechatUtil() {
+
+    }
+
+    private static WechatUtil single = null;
+
+    // 访问的微信接口地址
+    private static final String SEND_MSG_URL = "http://member.freshport.com";
+
+    // 返回error状态
+    public static final String SUCCESS = "0"; // 发送成功
+
+    public static final String ERROR = "1"; // 发送失败
+    
+    ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 5, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100),  new ThreadPoolExecutor.DiscardOldestPolicy());
+
+    public static synchronized WechatUtil getInstance() {
+        if (single == null) {
+            single = new WechatUtil();
+        }
+        return single;
+    }
+
+    public static class ThreadPoolTask implements Runnable{  
+        // 保存任务所需要的数据  
+        private HashMap<String, String> parameterMap;  
+  
+        ThreadPoolTask(HashMap<String, String> parameterMap) {  
+            this.parameterMap = parameterMap;  
+        }  
+  
+        public void run() {  
+            try {  
+                String info = HttpUtil.post(SEND_MSG_URL, parameterMap, null, null);
+                log.info("调用微信推送，返回信息:"+info);
+                if (StringUtils.isNotEmpty(info)) {
+                    JsonObject obj = new JsonParser().parse(info).getAsJsonObject();
+                    String error = obj.get("error").getAsString();
+                    if (error.equals(ERROR)) {
+                        // 失败
+                        log.error("手机号:" + parameterMap.get("sendphone") + "推送失败,原因:" + obj.get("message").getAsString() + ";");
+                    }
+                }
+            } catch (Exception e) {  
+                e.printStackTrace();  
+            }  
+            parameterMap = null;  
+        }  
+    }   
+    
+    /**
+     * 
+       
+     * sendWechatMsg(发送微信消息核心功能)    
+       
+     * @param   phones 手机号集合
+       
+     * @param  msgContent 消息内容    
+       
+     * @return String    DOM对象    
+       
+     * @Exception 异常对象
+     */
+    public void sendWechatMsg(List<String> phones, String msgContent) {
+        StringBuffer des = new StringBuffer();
+        String info = "";
+        for (String phone : phones) {
+            try {
+                Pattern p = Pattern.compile("\t|\r|\n");
+                Matcher m = p.matcher(msgContent);
+                msgContent = m.replaceAll("").trim();
+            	HashMap<String, String> parameterMap = new HashMap<String, String>();
+            	parameterMap.put("action", "sendTest");
+            	parameterMap.put("sendtxt", msgContent);
+            	parameterMap.put("sendphone", phone);
+            	threadPool.execute(new ThreadPoolTask(parameterMap));
+            } catch (Exception e) {
+                e.printStackTrace();
+                des.append("手机号:" + phone + "推送失败,原因:" + e.getMessage() + "; info:"+info);
+            }
+        }
+    }
+}
Index: src/main/resources/mapper/mySqlMapper/QueryCodeJobMapper.xml
===================================================================
--- src/main/resources/mapper/mySqlMapper/QueryCodeJobMapper.xml	(revision 28943)
+++ src/main/resources/mapper/mySqlMapper/QueryCodeJobMapper.xml	(revision 29042)
@@ -4,7 +4,7 @@
 
 
   <select id="find" resultType="com.novaone.entity.QueryCodeRetryJob">
-    SELECT id, jyjyzscxm, certificate_no, receive_time, sms_id, retry_count, create_time, update_time, message
+    SELECT id, query_code, certificate_no, receive_time, sms_id, retry_count, create_time, update_time, message
     FROM query_code_retry_job
   </select>
 
@@ -28,8 +28,8 @@
   <insert id="add" parameterType="com.novaone.entity.QueryCodeRetryJob" >
     INSERT INTO query_code_retry_job
     <trim prefix="(" suffix=")" suffixOverrides="," >
-      <if test="jyjyzscxm != null and jyjyzscxm != ''">
-        jyjyzscxm,
+      <if test="queryCode != null and queryCode != ''">
+        query_code,
       </if>
       <if test="certificateNo != null  and certificateNo != ''" >
         certificate_no,
@@ -54,8 +54,8 @@
       </if>
     </trim>
     <trim prefix="values (" suffix=")" suffixOverrides="," >
-      <if test="jyjyzscxm != null and jyjyzscxm != ''">
-        #{jyjyzscxm},
+      <if test="queryCode != null and queryCode != ''">
+        #{queryCode},
       </if>
       <if test="certificateNo != null and certificateNo != ''" >
         #{certificateNo},
@@ -84,8 +84,8 @@
   <update id="updateById" parameterType="com.novaone.entity.QueryCodeRetryJob">
     UPDATE query_code_retry_job
     <set>
-      <if test="jyjyzscxm != null and jyjyzscxm != ''">
-        jyjyzscxm = #{jyjyzscxm},
+      <if test="queryCode != null and queryCode != ''">
+        query_code = #{queryCode},
       </if>
       <if test="certificateNo != null  and certificateNo != ''" >
         certificate_no = #{certificateNo},
@@ -103,7 +103,7 @@
         update_time = #{updateTime},
       </if>
       <if test="message != null and message != ''" >
-        message
+        message = #{message}
       </if>
     </set>
     WHERE id = #{id}
Index: src/main/resources/mapper/sqlServerMapper/BgSyrsMapper.xml
===================================================================
--- src/main/resources/mapper/sqlServerMapper/BgSyrsMapper.xml	(nonexistent)
+++ src/main/resources/mapper/sqlServerMapper/BgSyrsMapper.xml	(revision 29042)
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
+<mapper namespace="com.novaone.fdao.BgSyrszDao">
+    <select id="findByCondition" parameterType="string" resultType="com.novaone.entity.BgSyrsz">
+        SELECT id, bm, jcka, syrmc, syrdh
+        FROM yw_bg_syrsz
+        <where>
+            <if test="bm != null and bm.length() > 0">
+                bm = #{bm}
+            </if>
+            <if test="jcka != null and jcka.length() > 0">
+                AND jcka = #{jcka}
+            </if>
+        </where>
+    </select>
+</mapper>
\ No newline at end of file
Index: src/main/resources/mapper/sqlServerMapper/HddzMapperMapper.xml
===================================================================
--- src/main/resources/mapper/sqlServerMapper/HddzMapperMapper.xml	(revision 28943)
+++ src/main/resources/mapper/sqlServerMapper/HddzMapperMapper.xml	(revision 29042)
@@ -19,7 +19,7 @@
   </update>
 
   <select id="findByBgdh" parameterType="string" resultType="com.novaone.entity.Hddz">
-    SELECT sfyjyjyzs,jyjyzs,bgdh,ywbh,jyjyzscxm FROM yw_hddz WHERE bgdh = #{bgdh};
+    SELECT sfyjyjyzs,jyjyzs,bgdh,ywbh,jyjyzscxm,bm,jcka FROM yw_hddz WHERE bgdh = #{bgdh};
   </select>
 
 </mapper>
\ No newline at end of file
