package nc.impl.th;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.net.ssl.SSLSession;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.Security;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.io.FileOutputStream;
import nc.bs.dao.BaseDAO;
import nc.bs.dao.DAOException;
import nc.bs.framework.common.InvocationInfoProxy;
import nc.bs.framework.common.NCLocator;
import nc.bs.framework.common.RuntimeEnv;
import nc.itf.uap.IUAPQueryBS;
import nc.jdbc.framework.processor.ArrayListProcessor;
import nc.jdbc.framework.processor.BeanListProcessor;
import nc.jdbc.framework.processor.ColumnProcessor;
import nc.jdbc.framework.processor.MapProcessor;
import nc.log.NcLog;
import nc.vo.bd.defdoc.DefdocVO;
import nc.vo.pu.m25.entity.InvoiceItemVO;
import nc.vo.pu.m25.entity.InvoiceVO;
import nc.vo.pub.BusinessException;
import nc.bs.pub.filesystem.IFileSystemService;
import nc.itf.uap.IVOPersistence;

import org.apache.commons.codec.digest.DigestUtils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import nc.itf.bd.defdoc.IDefdocService;
import nc.itf.th.IThOcrService;
import nc.pub.toolkits.Toolkits;
import nc.th.redistoken.RedisTokenManager;
import nc.vo.pub.filesystem.NCFileNode;
import nc.vo.pub.lang.UFDouble;
import nc.vo.pubapp.pattern.pub.SqlBuilder;
import nc.vo.th.ocr.OCRInvoiceVO;
import weaver.fna.invoice.utils.InvoiceCloudAESUtil;
/**
 * OCR接口实现
 * @author Administrator
 *
 */
public class ThOcrServiceImpl implements IThOcrService{
	
	private IVOPersistence IVOPersistence = (IVOPersistence) NCLocator.getInstance().lookup(IVOPersistence.class);
	private IUAPQueryBS iuap=(IUAPQueryBS) NCLocator.getInstance().lookup(IUAPQueryBS.class.getName());
	private String aesKey = "w34xx413y2x23w4y";
	private static String appId="1438490100786012161";
	private static String secret="80c8664aa7a444049b8ed49ed5095561";
	private static String cid="1438490101547343873";
	private String upurl="https://up.mypiaojia.com/api/invoiceApi/file/uploadFileSpilit";
	private String inverurl="https://api.mypiaojia.com/api/invoiceApi/invoice/ocr";
	//发票验伪地址
	private String person_local_valid = "https://api.mypiaojia.com/api/invoiceApi/invoice/person_local_valid";
	//发票锁定地址
	private String ec_comm = "https://api.mypiaojia.com/api/invoiceApi/invoice/ec_comm";
	//获取token地址
	private String buildToken="https://api.mypiaojia.com/api/invoiceApi/token/buildToken";
	//获取发票云发票地址
	private String sync_rt = "https://api.mypiaojia.com/api/invoiceApi/invoice/sync_rt";
	public String[] insert(ArrayList<?> arrlist) throws BusinessException {
		return this.IVOPersistence.insertVOList(arrlist);
	}
	
	
	@Override
	/**
	 * 获取token
	 */
	public String getToken(String billmaker) throws Exception {
		NcLog.info("=======获取token开始=======");
		//redis中获取用户token
		String userToken ="";
		 try {
			 userToken = RedisTokenManager.getToken(billmaker); 
		  }catch(Exception e){
			  // Redis 连接异常，执行相应的异常处理操作
			  e.printStackTrace();
			  throw new Exception(e.getMessage()+"请检查redis服务器是否启动！");
		  }		
				
		//token为空
		if(Toolkits.isEmpty(userToken)){
			
			//调用OCR接口
			userToken=getOcrToken(billmaker);
			//保存到redis，设置失效时间36000秒
			RedisTokenManager.setTokenTTL(billmaker,36000, userToken);
		}
		NcLog.info("=======token======="+userToken);
		NcLog.info("=======获取token结束=======");
		 return userToken;
	}

	
	
	/**
	 * 上传发票
	 * @throws Exception 
	 */
	public String uploadInvoice(String token,String vdef17,String invoicename) throws Exception {
		NcLog.info("=======上传发票开始=======");
		File file=new File(RuntimeEnv.getInstance().getNCHome()
			      +File.separator +"uploadfile" + File.separator+ vdef17+File.separator+invoicename);
		String resmsg=httpFilePost(upurl,token,file);
		String id="";
		if(null!=resmsg&&resmsg.indexOf("uploading")!=-1){
			 JSONObject json = JSONObject.parseObject(resmsg);
			 JSONObject data=json.getJSONObject("data");
			 if(null!=data){
				 id=data.getString("id");
			 }else{
				 throw new Exception(json.toString());
			 }
			
		}
		
		return resmsg;
	}



	/**
	 * OCR识别
	 * @throws Exception 
	 */
	@Override
	public String ocrIdentification(String token,String data) throws Exception {
		// TODO 自动生成的方法存根
		 NcLog.info("=======发票OCR识别开始=======");
		 JSONObject jsondata = JSONObject.parseObject(data);
		 JSONObject jsonobject = new JSONObject();
         jsonobject.put("image_index", jsondata.getJSONObject("data").getString("id"));
         jsonobject.put("fileTypeStr", jsondata.getJSONObject("data").getString("fileType"));
         jsonobject.put("flag", "13");
         jsonobject.put("is_save", "0");
         jsonobject.put("is_sync", "1");
         jsonobject.put("ocrMap","");
         jsonobject.put("operate_type",0);
         String json = doPost(inverurl,token,jsonobject.toString());
         NcLog.info("发票OCR识别返回json"+json);
		 return json;
	}
	
	@Override
	public void InvoiceCheck(String token,String fid)
			throws Exception {
		 NcLog.info("=======发票查验识别开始=======");
		 JSONObject jsonobject = new JSONObject();
		 jsonobject.put("id", fid);
         jsonobject.put("fid", fid);
         jsonobject.put("ic_cut", "0");
         jsonobject.put("operate_type","0");
         JSONObject req_base = new JSONObject();
         req_base.put("trace", fid);
         req_base.put("dev", "1");
         jsonobject.put("req_base",req_base);
         JSONObject json = JSONObject.parseObject(doPost(person_local_valid,token,jsonobject.toString()));
         
         NcLog.info("发票查验返回json"+json);
         JSONObject data=json.getJSONObject("data");
         if(data == null) {
        	 String msg=json.getJSONObject("actionMsg").getString("message");
			 throw new Exception(msg);
         }
	}
	
	
	/**
	 * OCR识别数据保存数据库
	 * @throws BusinessException 
	 */
	public void insertOCRdataInfo(ArrayList<OCRInvoiceVO> vos) throws BusinessException {
		insert(vos);
	}
	public String getOcrToken(String userid)  throws Exception{
		initSSL();  
	    URL url = new URL(buildToken);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setConnectTimeout(60000);
        connection.setReadTimeout(60000);
        connection.setRequestMethod("POST");
        connection.setRequestProperty("Content-Type", "application/json");
        connection.setRequestProperty("appkey", appId);
        long l = System.currentTimeMillis();
        Map<String,String> oamap = QueryOAUserid(userid);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("role", 1);
        map.put("name", oamap.get("lastname"));
        map.put("userId", oamap.get("id"));
        map.put("cid", cid);
        String s1 = JSONObject.toJSONString(map);
        String s2 = s1 + "&time=" + l + "&secret="+secret;
        byte[] requestBodyBytes = s2.getBytes("UTF-8");
        String newMd5 = DigestUtils.md5Hex(requestBodyBytes);
        String s4 = s1 + "&time=" + l + "&md5=" + newMd5;
        connection.setDoOutput(true);
        OutputStream outputStream = connection.getOutputStream();
        outputStream.write(s4.getBytes("UTF-8"));
        outputStream.flush();
        BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
        StringBuilder response = new StringBuilder();
        String inputLine;
        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();
        JSONObject json = JSONObject.parseObject(response.toString());
        NcLog.info("token:"+json.toString());
        String token = json.getString("data");
        
        if(token == null){
			 throw new BusinessException(json.toString());
		 }
		 
		 return token;
	  }
	
	


	 public  String httpFilePost(String uploadUrl,String token, File file) throws Exception {
		 
		//File file = new File(file);
		 String LINEND = "\r\n";
		 String boundary = UUID.randomUUID().toString();
		 FileInputStream fileInputStream = new FileInputStream(file);
		 initSSL();
	     URL url = new URL(uploadUrl);
	     HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
	     httpURLConnection.setDoInput(true);
	     httpURLConnection.setUseCaches(false);
	     httpURLConnection.setDoOutput(true);
	     httpURLConnection.setRequestMethod("POST");
	     httpURLConnection.setRequestProperty("connection", "keep-alive");
	     httpURLConnection.setRequestProperty("Charsert", "UTF-8");
	     httpURLConnection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
	     httpURLConnection.setRequestProperty("token", token);
	     httpURLConnection.setRequestProperty("Accept","*/*");
	     DataOutputStream outStream = new DataOutputStream(httpURLConnection.getOutputStream());
         StringBuilder stringBuilder = new StringBuilder();
         stringBuilder.append("--").append(boundary).append(LINEND);
         stringBuilder.append("Content-Disposition: form-data; name=\"file\"; filename=\"" + file.getName() + LINEND);
         stringBuilder.append("Content-Type: " + HttpURLConnection.guessContentTypeFromName(file.getName()) + LINEND);
         stringBuilder.append("Content-Transfer-Encoding: binary"+ LINEND);
         stringBuilder.append(LINEND);
 //        outStream.write(stringBuilder.toString().getBytes());
         outStream.writeUTF(stringBuilder.toString());
    	 InputStream is = new FileInputStream(file);
    	 byte[] buffer = new byte[1024];
    	 int len = 0;
    	 while ((len = is.read(buffer)) != -1){
    		 outStream.write(buffer, 0, len);
    	 }
    	 is.close();
    	 outStream.write(LINEND.getBytes());
    	 byte[] end_data = ("--" + boundary + "--" + LINEND).getBytes();
    	 outStream.write(end_data);
    	 outStream.flush();
         fileInputStream.close();
         String response = readStream(httpURLConnection.getInputStream());
         outStream.close();
         httpURLConnection.disconnect(); 
         NcLog.info("发票上传返回json:"+response);
		 return response;
			
		}
		 
	 private  String readStream(InputStream inputStream) throws IOException {
		 ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
		 byte[] buffer = new byte[1024];
		 int bytesRead;
		 while ((bytesRead = inputStream.read(buffer)) != -1) {
			 outputStream.write(buffer, 0, bytesRead);
			 }
		 byte[] bytes = outputStream.toByteArray();
		 String result = new String(bytes, "UTF-8");
		 outputStream.close();
		 return result;
		 }



		 public  String doPost(String pathUrl, String token,String data) throws Exception{
			OutputStreamWriter out = null;
	        BufferedReader br = null;
	        String result = "";
	        try {
	        	initSSL();
	        	URL url = new URL(pathUrl);
	        	//打开和url之间的连接
	            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
	            //设定请求的方法为"POST"，默认是GET
	            //post与get的不同之处在于post的参数不是放在URL字串里面，而是放在http请求的正文内。
	            conn.setRequestMethod("POST");
	  
	            //设置30秒连接超时
	            conn.setConnectTimeout(30000);
	            //设置30秒读取超时
	            conn.setReadTimeout(30000);
	  
	            // 设置是否向httpUrlConnection输出，因为这个是post请求，参数要放在http正文内，因此需要设为true, 默认情况下是false;
	            conn.setDoOutput(true);
	            // 设置是否从httpUrlConnection读入，默认情况下是true;
	            conn.setDoInput(true);
	  
	            // Post请求不能使用缓存
	            conn.setUseCaches(false);
	  
	            //设置通用的请求属性
	            conn.setRequestProperty("accept", "*/*");
	            conn.setRequestProperty("connection", "Keep-Alive");  //维持长链接
	            conn.setRequestProperty("Content-Type", "application/json;charset=utf-8");
	            conn.setRequestProperty("token", token);
	  
	            //连接，从上述url.openConnection()至此的配置必须要在connect之前完成，
	            conn.connect();
	  
	            /**
	             * 下面的三句代码，就是调用第三方http接口
	             */
	            //获取URLConnection对象对应的输出流
	            //此处getOutputStream会隐含的进行connect(即：如同调用上面的connect()方法，所以在开发中不调用上述的connect()也可以)。
	            out = new OutputStreamWriter(conn.getOutputStream(), "UTF-8");
	            //发送请求参数即数据
	            out.write(data);
	            //flush输出流的缓冲
	            out.flush();
	  
	            /**
	             * 下面的代码相当于，获取调用第三方http接口后返回的结果
	             */
	            //获取URLConnection对象对应的输入流
	            InputStream is = conn.getInputStream();
	            //构造一个字符流缓存
	            br = new BufferedReader(new InputStreamReader(is,"UTF-8"));
	            String str = "";
	            while ((str = br.readLine()) != null){
	                result += str;
	            }
	         //   System.out.println(result);
	            
	           /* JSONObject json = JSONObject.parseObject(result);
	            //获取主要数据
	            JSONObject datajson = json.getJSONObject("data");
	            System.out.println("datajson===="+datajson.toString());
	            JSONArray infosjson = datajson.getJSONArray("infos");
	            System.out.println("infosjson===="+infosjson.toString());
	            
	            for (Object infos : infosjson) {
	            	JSONObject infosObject =(JSONObject)infos;
	                String total=infosObject.getJSONObject("info").getJSONObject("comm_info").getJSONObject("price").getString("total");
	                System.out.println("total===="+total);
	            }*/
	            
	            //关闭流
	            is.close();
	            //断开连接，disconnect是在底层tcp socket链接空闲时才切断，如果正在被其他线程使用就不切断。
	            conn.disconnect();
	        }catch (Exception e) {
	        	throw new Exception(e);
	        }finally {
	            try {
	                if (out != null){
	                    out.close();
	                }
	                if (br != null){
	                    br.close();
	                }
	            } catch (IOException e) {
	            	throw new Exception(e);
	            }
	        } 
			return result;
		 }
		 
		 /**
			 * 
			 *  发票保存到文件夹里
			 *  vdef17     发票主键
			 *  fileName 发票名
			 *  file     选中的发票
			 * @throws IOException 
			 */
			public String saveUploadFile(String vdef17,String fileName,byte[] bytes) throws Exception {
		/*		NcLog.info("=====发票保存开始=====");
				String filepath =  RuntimeEnv.getInstance().getNCHome()
					      +File.separator +"uploadfile" + File.separator+ vdef17; // 文件保存的路径
				NcLog.info("文件保存的路径："+filepath);
				NcLog.info("原文件路径："+file.getPath());
				File folder = new File(filepath);
				if(!folder.exists() && !folder.isDirectory()){
					folder.mkdirs();
				}
				String newFileName = filepath + File.separator + fileName;
				NcLog.info("文件保存新路径："+newFileName);
				FileOutputStream outputStream = new FileOutputStream(newFileName);
				NcLog.info("=====FileOutputStream=====");
				FileInputStream fis = new FileInputStream(file);
		        byte[] buffer = new byte[1024];
		        int len;
		        NcLog.info("=====读取发票信息开始=====");
		        while ((len = fis.read(buffer)) != -1) {
		            outputStream.write(buffer, 0, len);
		        }
		        NcLog.info("=====读取发票信息结束=====");
		        outputStream.close();
		        fis.close();
		        NcLog.info("=====发票保存结束=====");*/
				
			//	byte[] bs = Base64.decode(file.trim());
				
				NcLog.info("=====发票保存开始=====");
			//	NcLog.info("=====bytes:"+bytes.length+"=====");
				String filepath =  RuntimeEnv.getInstance().getNCHome()
					      +File.separator +"uploadfile" + File.separator+ vdef17; // 文件保存的文件夹
				String newFileName = filepath + File.separator + fileName;
				NcLog.info("文件保存新路径："+newFileName);
				
				String savefilepath=SaveTempFile(filepath,newFileName,bytes);
//				Upload(vdef17,savefilepath,newFileName,InvocationInfoProxy.getInstance().getUserId());
				
				return savefilepath;
				
			 }
			
			
			
			/**
			 * 保存文件
			 * 
			 * @param filepath  文件夹路径
			 * @param fileName  文件名路径
			 * @param bs  文件流
			 * @return  返回文件保存的路径
			 * @throws Exception 
			 */
			public String SaveTempFile(String filepath,String fileName,byte[] bytes) throws Exception  {
				FileOutputStream fos = null;
				BufferedOutputStream bos=null;
				try {
					File folder = new File(filepath);
					if(!folder.exists() && !folder.isDirectory()){
						folder.mkdirs();
					}
					fos = new FileOutputStream(fileName);
					bos = new BufferedOutputStream(fos);
					bos.write(bytes);
				} catch (FileNotFoundException e1) {
					// TODO 自动生成的 catch 块
					e1.printStackTrace();
					NcLog.info("保存发票FileNotFoundException异常："+e1.getMessage());
					throw new Exception("保存发票FileNotFoundException异常："+e1.getMessage());
					
				} catch (IOException e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
					NcLog.info("保存发票IOException异常："+e.getMessage());
					throw new Exception("保存发票IOException异常："+e.getMessage());
				}finally {
					if (bos != null) {
						try {
							bos.close();
						} catch (IOException e) {
							e.printStackTrace();
							NcLog.info("关闭bos流异常："+e.getMessage());
							throw new Exception("关闭bos流异常："+e.getMessage());
						}
					  }
					}
					
					if (fos != null) {
						try {
							fos.close();
						} catch (IOException e) {
							e.printStackTrace();
							NcLog.info("关闭fos流异常："+e.getMessage());
							throw new Exception("关闭fos流异常："+e.getMessage());
						}
					}
					
				       return filepath;
			      }
			
	
			
			/**
			 * NC文件上传
			 * @param parentPath 单据主键pk_jkbx
			 * @param newFile 文件路径
			 * @param filename 文件名
			 * @param user_code 创建人
			 * @return 0表示上传成功,-1表示失败
			 * @throws BusinessException 
			 * @throws IOException 
			 */
			public int Upload(String parentPath, String filepath, String filename,String user_code) throws BusinessException, IOException {
				NcLog.info("============防止重复上传相同名称的附件开始============");
				QueryFile(parentPath, filename);
				NcLog.info("============防止重复上传相同名称的附件结束============");
				File file = new File(filepath);
				NcLog.info("文件路径file："+file.getPath());
				Long fileLen = file.length();
				String creator = user_code;
				NCFileNode node = null;
				InputStream fileinput = null;
				try {
					fileinput = new FileInputStream(file);
					NcLog.info("FileInputStream："+fileinput);
					IFileSystemService service = (IFileSystemService) NCLocator
							.getInstance().lookup(IFileSystemService.class);
					NcLog.info("接口service开始："+service);
					node = service.createNewFileNodeWithStream(parentPath, filename,
							creator, fileinput, fileLen);
					NcLog.info("接口service结束："+node);
				} catch (FileNotFoundException e) {
					e.printStackTrace();
					NcLog.info("FileNotFoundException保存失败："+e.getMessage());
					throw new FileNotFoundException();
				} catch (IOException e) {
					e.printStackTrace();
					NcLog.info("IOException保存失败："+e.getMessage());
					throw new IOException();
				} catch (BusinessException e) {
					e.printStackTrace();
					NcLog.info("BusinessException保存失败："+e.getMessage());
					throw new BusinessException();
				} finally {
					try {
						fileinput.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
				if (node == null) {
					NcLog.info("-1表示失败："+"【"+-1+"】");
					return -1;
				}
				NcLog.info("0表示上传成功："+"【"+0+"】");
				return 0;
				
			}
		
			/**
			 * 防止重复上传相同名称的附件
			 * 
			 * @param parentPath
			 *            单据主键
			 * @param filename
			 *            文件名
			 * @throws BusinessException 
			 */
			public void QueryFile(String parentPath, String filename) throws BusinessException  {
				try {
					String path = parentPath + "/" + filename;
					IUAPQueryBS iuap= (IUAPQueryBS) NCLocator.getInstance().lookup(IUAPQueryBS.class.getName());
					String sql = "select filepath from sm_pub_filesystem where filepath = '"
							+ path + "'";
					@SuppressWarnings("unchecked")
					List<Object[]> filelist = (List<Object[]>) iuap.executeQuery(sql,
							new ArrayListProcessor());
					if (filelist != null && filelist.size() > 0) {// 如果有附件，则先删除
						IFileSystemService service = (IFileSystemService) NCLocator
								.getInstance().lookup(IFileSystemService.class);
						String[] arg = new String[] { path };
						service.deleteNCFileNodes(arg);
					}
				} catch (DAOException e) {
					e.printStackTrace();
					NcLog.info("=====DAOException防止重复上传相同名称的附件====="+e.getMessage());
					throw new DAOException();
				} catch (BusinessException e) {
					e.printStackTrace();
					NcLog.info("=====BusinessException防止重复上传相同名称的附件====="+e.getMessage());
					throw new BusinessException();
				}
			}
		
			/**
			 * 获取home路径
			 */
			public String getNCHomePath() {
			
				return RuntimeEnv.getInstance().getNCHome();
			}


			/**
			 * 删除home里对应的发票
			 */
			public Boolean deleteFile(String filepath)  {
				 NcLog.info("=====删除home里对应的发票开始=====");
				//删除home发票文件夹里的对应发票 add by ZTH
				String deletefilepath =  RuntimeEnv.getInstance().getNCHome()
					      +File.separator +"uploadfile" + File.separator+ filepath; // 文件保存的路径
				
				 File file = new File(deletefilepath);
				 
				 Boolean bo= file.delete();
				 NcLog.info("=====删除home里对应的发票结束=====");
				 return bo;
				 
				
			}


			/**
			 * 由于删除太慢，改成自定义档案数据停用
			 * @throws BusinessException 
			 */
			public DefdocVO[] enablestateDate(String filepath,String[] filname) throws BusinessException {
				 NcLog.info("=====改成自定义档案数据停用开始=====");
				 DefdocVO[] deletevos=QryDefdocvoInfo(filname[1]);
				 IDefdocService idefservice = NCLocator.getInstance().lookup(IDefdocService.class);
				 DefdocVO defvo =deletevos[0];
				 defvo.setAttributeValue("enablestate", 3);//停用
				 DefdocVO[] defdocVOs= idefservice.updateDefdocs(InvocationInfoProxy.getInstance().getGroupId(),deletevos);
				 NcLog.info("=====改成自定义档案数据停用结束=====");
				 return defdocVOs;
			}
			
			
			private DefdocVO[]  QryDefdocvoInfo(String name){
		    	String sql = "select * from  bd_defdoc where  nvl(dr, 0) = 0 and pk_defdoclist="
		    			+ "(select pk_defdoclist from bd_defdoclist where code='OCRTHNC' and nvl(dr,0)=0) and memo='" + name + "' ";
		    	ArrayList<Object> arrayvos=null;
		    	try {
					arrayvos=(ArrayList<Object>) iuap.executeQuery(sql, new BeanListProcessor(DefdocVO.class));
				} catch (BusinessException e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				}
		    	
		    	if (arrayvos==null) {
		  			return new DefdocVO[0];
		  		}else {
		  			return arrayvos.toArray(new DefdocVO[0]);
		  		}
		    	
		    }


			/**
			 * 获取"+vdef17+"文件夹下所有发票名
			 */
			public List<String> getInvoiceInfo(String vdef17) {
				String filepath =  RuntimeEnv.getInstance().getNCHome()
					      +File.separator +"uploadfile" + File.separator+ vdef17; // 文件保存的路径
				List<String> filewjlis=getFileNames(filepath);
				
				return filewjlis;
			} 
		 
			/**
		     * 得到文件名称
		     *
		     * @param path 路径
		     * @return {@link List}<{@link String}>
		     */
		    private  List<String> getFileNames(String path) {
		        File file = new File(path);
		        if (!file.exists()) {
		            return null;
		        }
		        List<String> fileNames = new ArrayList<String>();
		        return getFileNames(file, fileNames);
		    }

		/**
		     * 得到文件名称
		     *
		     * @param file      文件
		     * @param fileNames 文件名
		     * @return {@link List}<{@link String}>
		     */
		    private  List<String> getFileNames(File file, List<String> fileNames) {
		        File[] files = file.listFiles();
		        for (File f : files) {
		            if (f.isDirectory()) {
		                getFileNames(f, fileNames);
		            } else {
		                fileNames.add(f.getName());
		            }
		        }
		        return fileNames;
		    }

		    
		@Override
		public void UpdateInvoiceStatus(String status, InvoiceVO[] vos) throws Exception {
			//T提交——1  S收回——0  //Y审批通过——2 //R驳回
			
			for (InvoiceVO invoiceVO : vos) {
				//没有发票不传发票云
				if(invoiceVO.getParentVO().getVdef17() == null) {
					continue;
				}
				
					NcLog.info("=======锁定发票、修改开始=======");
					Map<String,String> oamap = QueryOAUserid(invoiceVO.getParent().getAttributeValue("billmaker").toString());
					InvoiceItemVO[] arrInvoiceItemVO = (InvoiceItemVO[]) invoiceVO.getChildren(InvoiceItemVO.class);
					List<Map<Object, Object>> listMapVbdef20 = new ArrayList<Map<Object, Object>>();
					List<String> listVbdef20 = new ArrayList<String>();
					for (InvoiceItemVO invoiceItemVO : arrInvoiceItemVO) {
						if(invoiceItemVO.getVbdef20() != null && !"".equals(invoiceItemVO.getVbdef20())) {
							String[] arrVbdef20 = invoiceItemVO.getVbdef20().split(",");
							for(String Vbdef20 : arrVbdef20) {
								//当前单据该发票价税合计，无税金额，税额
								UFDouble norigtaxmny = invoiceItemVO.getNorigtaxmny();
								UFDouble norigmny = invoiceItemVO.getNorigmny();
								UFDouble ntax = invoiceItemVO.getNtax();
								StringBuffer sql1 = new StringBuffer();
								sql1.append("SELECT");
								sql1.append(" shortname2,");
								sql1.append(" shortname,");
								sql1.append(" shortname3");
								sql1.append(" FROM");
								sql1.append(" bd_defdoc");
								sql1.append(" WHERE");
								sql1.append(" pk_defdoc = '"+Vbdef20+"'");
								Map<String,String> mapdb = (Map<String, String>) iuap.executeQuery(sql1.toString(), new MapProcessor());
								//该发票价税合计
								UFDouble shortname2 = new UFDouble(mapdb.get("shortname2"));
								//该发票无税金额
								UFDouble shortname = new UFDouble(mapdb.get("shortname"));
								//该发票税额
								UFDouble shortname3 = new UFDouble(mapdb.get("shortname3"));
								//审批的情况下
								if("Y".equals(status)){
									int index = invoiceItemVO.getVbdef16().indexOf("—");
									//去掉拼接时间戳
							    	String code = index == -1 ? invoiceItemVO.getVbdef16() : invoiceItemVO.getVbdef16().substring(0, index);
							    	//查询该发票已使用价税合计,无税金额，税额
									StringBuffer sql = new StringBuffer();
									sql.append("SELECT");
									sql.append(" SUM( po_invoice_b.norigtaxmny ) as norigtaxmny,");
									sql.append(" SUM( po_invoice_b.norigmny ) as norigmny,");
									sql.append(" SUM( po_invoice_b.ntax ) as ntax");
									sql.append(" FROM");
									sql.append(" po_invoice po_invoice");
									sql.append(" LEFT JOIN po_invoice_b po_invoice_b ON po_invoice.pk_invoice = po_invoice_b.pk_invoice ");
									sql.append(" WHERE");
									sql.append(" po_invoice.fbillstatus <> '0' ");
									sql.append(" AND po_invoice.fbillstatus <> '1' ");
									sql.append(" AND po_invoice.vbillcode <> '"+invoiceVO.getParentVO().getVbillcode()+"'");
									sql.append(" AND po_invoice_b.vbdef20 IN ( SELECT pk_defdoc FROM bd_defdoc WHERE code LIKE '"+code+"%' )");
									sql.append(" AND nvl(po_invoice.dr,0) = 0");
									sql.append(" AND nvl(po_invoice_b.dr,0) = 0");
									Map<String,String> mappo = (Map<String, String>) iuap.executeQuery(sql.toString(), new MapProcessor());
									//价税合计
									Object objectNorigtaxmny = mappo.get("norigtaxmny");
									//无税金额
									Object objectNorigmny = mappo.get("norigmny");
									//税额
									Object objectNtax = mappo.get("ntax");
									UFDouble sumNorigtaxmny = new UFDouble(objectNorigtaxmny == null ? 0.00 : Double.valueOf(objectNorigtaxmny.toString()));
									UFDouble sumNorigmny = new UFDouble(objectNorigmny == null ? 0.00 : Double.valueOf(objectNorigmny.toString()));
									UFDouble sumNtax = new UFDouble(objectNtax == null ? 0.00 : Double.valueOf(objectNtax.toString()));
									if(sumNorigtaxmny.add(norigtaxmny).compareTo(shortname2)>0) {
										 throw new Exception("行:"+invoiceItemVO.getCrowno()+"发票可用余额不足!差:"+(sumNorigtaxmny.add(norigtaxmny)).sub(shortname2));
									}
									if(sumNorigmny.add(norigmny).compareTo(shortname)>0) {
										 throw new Exception("行:"+invoiceItemVO.getCrowno()+"无税金额大于发票可用金额!差:"+(sumNorigmny.add(norigmny)).sub(shortname));
									}
									if(sumNtax.add(ntax).compareTo(shortname3)>0) {
										 throw new Exception("行:"+invoiceItemVO.getCrowno()+"税额大于发票可用税额!差:"+(sumNtax.add(ntax)).sub(shortname3));
									}
								}
								StringBuffer sql2 = new StringBuffer();
								sql2.append("SELECT");
								sql2.append(" name5");
								sql2.append(" FROM");
								sql2.append(" bd_defdoc ");
								sql2.append(" WHERE");
								sql2.append(" pk_defdoc = '"+Vbdef20+"'");
								String name5 = (String) iuap.executeQuery(sql2.toString(), new ColumnProcessor());
								Map<Object, Object> map = new  HashMap<Object, Object>();
								map.put("norigtaxmny", norigtaxmny.toString());
								map.put("name5",name5);
								listMapVbdef20.add(map);
								listVbdef20.add(name5);
							}
						}
					}
					if(listMapVbdef20.size() > 0) {
						JSONObject bodyJson = new JSONObject();
						//发票云团队id
						bodyJson.put("cid", cid);
						//userId报销人id（OA）
						bodyJson.put("userId", oamap.get("id"));
						//userId报销人id（OA）
						bodyJson.put("flag", "3");
						//发票云发票ID数组
						bodyJson.put("fids", listVbdef20.toArray());
						NcLog.info("发票锁定返回json:"+UpdateInvoiceOCR(bodyJson.toString()));
						//0 未报销 1 报销中 2已报销
						String  sreim = "0";
						if("Y".equals(status)) {
							sreim = "2";
						}else if("T".equals(status)) {
							sreim = "1";
						}
						JSONObject bodyJson1 = new JSONObject();
						bodyJson1.put("cid", cid);
						bodyJson1.put("userId", oamap.get("id"));
						bodyJson1.put("flag", "2");
						bodyJson1.put("sreim",sreim);
						JSONArray arrinfos = new JSONArray();
						for (Map<Object, Object> map : listMapVbdef20) {
							long date = System.currentTimeMillis()/ 1000;
							JSONObject bodyJson2 = new JSONObject();
							bodyJson2.put("dataid", invoiceVO.getParent().getAttributeValue("pk_invoice"));
							bodyJson2.put("number", invoiceVO.getParent().getAttributeValue("pk_invoice"));
							bodyJson2.put("amount", map.get("norigtaxmny"));
							bodyJson2.put("uid", oamap.get("id"));
							bodyJson2.put("date",Long.toString(date));
							bodyJson2.put("name", invoiceVO.getParent().getAttributeValue("pk_invoice"));
							bodyJson2.put("fid", map.get("name5"));
							bodyJson2.put("cid", cid);
							arrinfos.add(bodyJson2);
						}
						bodyJson1.put("infos", arrinfos);
						NcLog.info("发票锁定修改返回json:"+UpdateInvoiceOCR(bodyJson1.toString()));
					}
			}
		}
		
		/*
		 * 发票锁定
		 */
		private String UpdateInvoiceOCR(String bodyJson) throws Exception {
			String content =  InvoiceCloudAESUtil.startAssemble(aesKey, secret, bodyJson);
			initSSL();
	        URL url = new URL(ec_comm);
	        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
	        connection.setRequestMethod("POST");
	        connection.setRequestProperty("content-type", "application/json");
	        connection.setRequestProperty("appkey", appId);
	        connection.setDoOutput(true);
	        DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
	        wr.writeBytes(content);
	        wr.flush();
	        wr.close();
	        int responseCode = connection.getResponseCode();
	        if (responseCode != 200) {
	            throw new Exception("HTTP Error: " + responseCode);
	        }
	        StringBuilder response = new StringBuilder();
	        BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
	        String inputLine;
	        while ((inputLine = in.readLine()) != null) {
	            response.append(inputLine);
	        }
	        in.close();
	        JSONObject jsonResponse = JSONObject.parseObject(response.toString());
	        String data = jsonResponse.getString("data");
	        if (data == null) {
	            throw new BusinessException(response.toString());
	        }
	        return jsonResponse.toString();
		}
		
		
		/**
		 * 从发票云获取发票
		 */
		@Override
		public JSONObject SelectORCInvoice(String token) throws Exception{
			NcLog.info("=======发票云获取发票开始=======");
			JSONObject jsonobject = new JSONObject();
			jsonobject.put("tag", "1");
			jsonobject.put("sreim", "0");
			jsonobject.put("mask", "281474976710655");
			jsonobject.put("mext", "4031");
			jsonobject.put("page_size", "9999");
			jsonobject.put("start_pos", "0");
			JSONArray sorts = new JSONArray();
			jsonobject.put("sorts", sorts);
			String json = doPost(sync_rt,token,jsonobject.toString());
			NcLog.info("发票云获取发票返回json:"+json.toString());
	        return JSONObject.parseObject(json);
	        
		}
		
		/**
		 *  将发票数据存储关联表
		 */
		@Override
		public void addORC(Map<String,String> map) throws Exception {
			// 组装新增SQL语句
			InvocationInfoProxy.getInstance().getUserDataSource();
			StringBuilder insertSQL = new StringBuilder("INSERT INTO ocr_defdoc VALUES (");
			insertSQL.append("'").append(map.get("KYHSJE")).append("', ");
			insertSQL.append("'").append(map.get("KYWSJE")).append("', ");
			insertSQL.append("'").append(map.get("JYSE")).append("', ");
			insertSQL.append("'").append(map.get("FPXZ")).append("', ");
			insertSQL.append("'").append(map.get("NUMBERID")).append("', ");
			insertSQL.append("'").append(map.get("VDEF17")).append("') ");
			new BaseDAO().executeUpdate(insertSQL.toString());
			
		}
		
		/**
		 * 删除发票关联表数据
		 * 
		 */
		@Override
		public void deleteORC(String number,String vdef17,int type) throws Exception {
			String[] arrNumber = number.split(",");
			StringBuilder deleteSQL = new StringBuilder("DELETE FROM ocr_defdoc");
			deleteSQL.append(" WHERE");
			deleteSQL.append(" vdef17 = '"+vdef17+"'");
			//注意发票识别的信息number没有时间戳,发票云获取的信息有时间戳
			//0本地上传  1发票获取
			if(type == 1) {
				if(arrNumber.length == 1) {
					deleteSQL.append(" AND SUBSTR(NUMBERID, 1, INSTR(NUMBERID, '—')-1) = '"+arrNumber[0].toString()+"'");
		    	}else {
		    		SqlBuilder sqlb = new SqlBuilder();
					sqlb.append("SUBSTR(NUMBERID, 1, INSTR(NUMBERID, '—')-1)", arrNumber);
					deleteSQL.append(" AND  "+sqlb.toString());
		    	}
			}else {
				if(arrNumber.length == 1) {
					deleteSQL.append(" AND NUMBERID = '"+arrNumber[0].toString()+"'");
		    	}else {
		    		SqlBuilder sqlb = new SqlBuilder();
					sqlb.append("NUMBERID", arrNumber);
					deleteSQL.append(" AND  "+sqlb.toString());
		    	}	
			}
			
			
			
			new BaseDAO().executeUpdate(deleteSQL.toString());
		}
		
		
		/*
		 * 查询OA信息
		 */
		private Map<String,String> QueryOAUserid(String cuserid) throws Exception {
			StringBuffer sql = new StringBuffer();
			sql.append("SELECT");
			sql.append(" oa_user.id,");
			sql.append(" oa_user.lastname");
			sql.append(" FROM");
			sql.append(" sm_user sm_user");
			sql.append(" left join oa_user oa_user on sm_user.pk_psndoc = TRIM(oa_user.outkey)");
			sql.append(" WHERE");
			sql.append(" sm_user.cuserid = '"+cuserid+"'");
			Map<String,String> map = (Map<String, String>) iuap.executeQuery(sql.toString(), new MapProcessor());
			if(map.get("id") == null) {
				throw new Exception("获取oaid失败，请检查用户和人员是否关联!");
			}
			return map;
		}
		
	
		/*
		 * 跳过SSL
		 */
		private  void initSSL() throws Exception {
			System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2");  
	        Security.setProperty("ssl.SocketFactory.provider", "");  
	        Security.setProperty("ssl.ServerSocketFactory.provider", "");  
	  
	        TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() {  
	            @Override  
	            public java.security.cert.X509Certificate[] getAcceptedIssuers() {  
	                return null;  
	            }  
	  
	            @Override  
	            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {  
	            }  
	  
	            @Override  
	            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {  
	            }  
	        }  
	        };  
	  
	        SSLContext sc = SSLContext.getInstance("TLS");  
	        sc.init(null, trustAllCerts, new java.security.SecureRandom());  
	        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());  
	  
	        HostnameVerifier allHostsValid = new HostnameVerifier(){  
	            @Override  
	            public boolean verify(String hostname, SSLSession session) {  
	                return true;  
	            }  
	        };  
	        HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);  
		}
	
		
}
