tinvoicebill.java 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733
  1. package tinvoicebill;
  2. import baseclass.PaoCust;
  3. import net.sf.json.JSONArray;
  4. import net.sf.json.JSONObject;
  5. import openapi.base.data.Row;
  6. import openapi.base.data.Rows;
  7. import openapi.base.data.db.DBConnect;
  8. import openapi.tools.Math;
  9. import openapi.tools.nuonuo.OpenApi;
  10. import org.apache.commons.codec.binary.Base64;
  11. import p2.application.doclink.Doclinks;
  12. import p2.p2server.P2Server;
  13. import p2.pao.PaoRemote;
  14. import p2.pao.PaoSet;
  15. import p2.pao.PaoSetRemote;
  16. import p2.util.P2AppException;
  17. import p2.util.P2Exception;
  18. import p2.webclient.system.controller.UploadFile;
  19. import p2.webclient.system.controller.UploadFileOSS;
  20. import p2.webclient.system.controller.Utility;
  21. import tinvoiceapply.tinvoiceapply;
  22. import tinvoicebillitem.tinvoicebillitem;
  23. import javax.crypto.Cipher;
  24. import javax.crypto.spec.SecretKeySpec;
  25. import java.io.BufferedInputStream;
  26. import java.io.ByteArrayOutputStream;
  27. import java.io.File;
  28. import java.io.IOException;
  29. import java.net.HttpURLConnection;
  30. import java.net.URL;
  31. import java.net.URLEncoder;
  32. import java.security.KeyFactory;
  33. import java.security.PublicKey;
  34. import java.security.spec.X509EncodedKeySpec;
  35. import java.util.Calendar;
  36. import java.util.Iterator;
  37. import java.util.Properties;
  38. public class tinvoicebill extends PaoCust {
  39. public tinvoicebill(PaoSet arg0) {
  40. super(arg0);
  41. }
  42. @Override
  43. public void init() throws P2Exception {
  44. super.init();
  45. if (!toBeAdded()) {
  46. if (getOwner() instanceof tinvoiceapply && "审核".equals(getOwner().getString("fstatus"))) {
  47. if ("2".equals(getString("status"))) {
  48. setFieldFlag(new String[]{"fnotes", "billInfoNo"}, READONLY, true);
  49. }
  50. }
  51. }
  52. }
  53. @Override
  54. public void add() throws P2Exception {
  55. super.add();
  56. if (getOwner() instanceof tinvoiceapply) {
  57. setValue("tinvoiceapplyid", getOwner().getUniqueIDValue(), 11L);
  58. }
  59. }
  60. @Override
  61. public void canDelete() throws P2Exception {
  62. super.canDelete();
  63. if (getOwner() instanceof tinvoiceapply && "审核".equals(getOwner().getString("fstatus"))) {
  64. if ("蓝".equals(getString("frb"))) {
  65. throw new P2AppException("", "审核状态下蓝票不可删除");
  66. }
  67. if ("2".equals(getString("status"))) {
  68. throw new P2AppException("", "已完成开票,不可删除");
  69. }
  70. }
  71. }
  72. @Override
  73. public void delete(long l) throws P2Exception {
  74. super.delete(l);
  75. }
  76. public void addbillitemnos(PaoSetRemote tinvoicebillitem_view) throws P2Exception {
  77. PaoSetRemote tinvoicebillitemSet = getPaoSet("tinvoicebillitem");
  78. Iterator<PaoRemote> it = tinvoicebillitem_view.getSelection().iterator();
  79. while (it.hasNext()) {
  80. PaoRemote tinvoiceapplyorder = it.next();
  81. PaoRemote tinvoicebillitem = tinvoicebillitemSet.addAtEnd();
  82. tinvoicebillitem.setValue("tinvoiceapplyordid", tinvoiceapplyorder.getLong("tinvoiceapplyordid"));
  83. tinvoicebillitem.setValue("goodscode", tinvoiceapplyorder.getString("fitemno"));
  84. tinvoicebillitem.setValue("goodsname", tinvoiceapplyorder.getString("fitemname"));
  85. tinvoicebillitem.setValue("spectype", tinvoiceapplyorder.getString("fspec"));
  86. tinvoicebillitem.setValue("unit", tinvoiceapplyorder.getString("funit"));
  87. tinvoicebillitem.setValue("num", tinvoiceapplyorder.getDouble("finvoiceqty"), 11L);
  88. tinvoicebillitem.setValue("price", tinvoiceapplyorder.getDouble("fprice"), 11L);
  89. tinvoicebillitem.setValue("taxincludedamount", tinvoiceapplyorder.getDouble("finvoiceamount"), 11L);
  90. }
  91. }
  92. /**
  93. * 发票查询
  94. *
  95. * @return
  96. */
  97. public void queryInvoice() throws P2Exception {
  98. if (getString("status").equals("2") && "红".equals(getString("frb"))) {
  99. return;
  100. }
  101. String finvoiceserialnum = getString("finvoiceserialnum");//发票流水号
  102. JSONObject contentObject = new JSONObject();
  103. contentObject.put("isOfferInvoiceDetail", "1");
  104. JSONArray serialNosArray = new JSONArray();
  105. serialNosArray.add(finvoiceserialnum);
  106. contentObject.put("serialNos", serialNosArray);
  107. JSONObject object = new OpenApi().requestApi("nuonuo.ElectronInvoice.queryInvoiceResult", contentObject.toString());
  108. if (object.getString("code").equalsIgnoreCase("E0000")) {
  109. JSONArray resultArray = object.getJSONArray("result");
  110. for (Object o : resultArray) {
  111. JSONObject resultObject = (JSONObject) o;
  112. String status = resultObject.getString("status");
  113. String statusMsg = resultObject.getString("statusMsg");
  114. setValue("status", status, 11L);
  115. setValue("msg", statusMsg, 11L);
  116. if (status.equals("2")) {
  117. if (resultObject.containsKey("pdfUrl")) {
  118. String pdfUrl = resultObject.getString("pdfUrl");
  119. if (getString("pdfUrl").equals("")) {
  120. upLoadDocUrl(pdfUrl, "发票pdf地址");
  121. }
  122. setValue("pdfUrl", pdfUrl, 11L);
  123. }
  124. if (resultObject.containsKey("paperPdfUrl")) {
  125. String paperPdfUrl = resultObject.getString("paperPdfUrl");
  126. if (getString("paperPdfUrl").equals("")) {
  127. upLoadDocUrl(paperPdfUrl, "纸票pdf地址");
  128. }
  129. setValue("paperPdfUrl", paperPdfUrl, 11L);
  130. }
  131. if (resultObject.containsKey("invoiceCode")) {
  132. String invoiceCode = resultObject.getString("invoiceCode");
  133. setValue("invoiceCode", invoiceCode, 11L);
  134. }
  135. if (resultObject.containsKey("invoiceNo")) {
  136. String invoiceNo = resultObject.getString("invoiceNo");
  137. setValue("invoiceNo", invoiceNo, 11L);
  138. }
  139. createPrintStr(getString("invoiceCode"), getString("invoiceNo"), Double.parseDouble(resultObject.getString("orderAmount")));
  140. if ("红".equals(getString("frb"))) {
  141. //红票查询成功后,更新订单已开票数量
  142. DBConnect dbConnect = new DBConnect();
  143. Rows rows = dbConnect.runSqlQuery("select t3.saorderdetailid,sum(t2.taxincludedamount)as taxincludedamount from tinvoicebill t1\n" +
  144. "inner join tinvoicebillitem t2 on t1.siteid=t2.siteid and t1.tinvoiceapplyid=t2.tinvoiceapplyid and t1.tinvoicebillid=t2.tinvoicebillid\n" +
  145. "inner join tinvoiceapplyorder t3 on t2.siteid=t3.siteid and t2.tinvoiceapplyid=t3.tinvoiceapplyid and t2.tinvoiceapplyordid=t3.tinvoiceapplyordid\n" +
  146. "where t1.tinvoicebillid='" + getUniqueIDValue() + "' group by t3.saorderdetailid");
  147. PaoSetRemote saorderdetailSet = getPaoSet("$saorderdetail", "saorderdetail", "siteid='" + getString("siteid") + "' and saorderdetailid in " + rows.getInWhere("saorderdetailid"));
  148. int i = 0;
  149. while (saorderdetailSet.getPao(i) != null) {
  150. for (Row row : rows) {
  151. if (String.valueOf(saorderdetailSet.getPao(i).getUniqueIDValue()).equalsIgnoreCase(row.getString("saorderdetailid"))) {
  152. double foldinvoiceamount = saorderdetailSet.getPao(i).getDouble("finvoiceamount");
  153. saorderdetailSet.getPao(i).setValue("finvoiceamount", Math.add(foldinvoiceamount, row.getDouble("taxincludedamount")), 11L);
  154. double sainvoiceamount = -row.getDouble("taxincludedamount");
  155. /**
  156. * 更新发货单已开票金额
  157. */
  158. PaoSetRemote sainvoicedetailSet = saorderdetailSet.getPao(i).getPaoSet("sainvoicedetail");
  159. sainvoicedetailSet.setOrderBy("sainvoicedetailid");
  160. int n = 0;
  161. while (sainvoicedetailSet.getPao(n) != null) {
  162. if (sainvoicedetailSet.getPao(n).getPaoSet("SAINVOICE").getPao(0).getString("").equals("关闭")) {
  163. double finvoiceamount_sainvoice = sainvoicedetailSet.getPao(n).getDouble("famount");//发货单已开票金额
  164. if (finvoiceamount_sainvoice > 0) {//表示已开票
  165. double fneedinvoiceamount_sainvoice = finvoiceamount_sainvoice;//发货单应减开票金额
  166. if (fneedinvoiceamount_sainvoice > sainvoiceamount) {
  167. fneedinvoiceamount_sainvoice = sainvoiceamount;
  168. }
  169. sainvoicedetailSet.getPao(n).setValue("finvoiceamount", baseclass.tools.Math.sub(finvoiceamount_sainvoice, fneedinvoiceamount_sainvoice), 11L);
  170. sainvoiceamount = baseclass.tools.Math.sub(sainvoiceamount, fneedinvoiceamount_sainvoice);
  171. }
  172. }
  173. n++;
  174. }
  175. }
  176. }
  177. i++;
  178. }
  179. }
  180. }
  181. }
  182. }
  183. setValue("result", object.toString(), 11L);
  184. }
  185. /**
  186. * 根据蓝票生成红票
  187. *
  188. * @throws P2Exception
  189. */
  190. public long addRedBill() throws P2Exception {
  191. PaoSetRemote tinvoicebillitemSet = getPaoSet("tinvoicebillitem");
  192. PaoRemote redBill = getThisPaoSet().addAtEnd();
  193. redBill.setValue("tinvoiceapplyid", getLong("tinvoiceapplyid"), 11L);
  194. redBill.setValue("frb", "红", 11L);
  195. redBill.setValue("fblueinvoiceid", getUniqueIDValue(), 11L);//蓝票ID
  196. PaoSetRemote redBillItemset = redBill.getPaoSet("tinvoicebillitem");
  197. tinvoicebillitemSet.copy(redBillItemset);
  198. int i = 0;
  199. while (redBillItemset.getPao(i) != null) {
  200. redBillItemset.getPao(i).setValue("tinvoicebillid", redBill.getUniqueIDValue(), 11L);
  201. redBillItemset.getPao(i).setValue("num", -redBillItemset.getPao(i).getDouble("num"), 11L);
  202. redBillItemset.getPao(i).setValue("taxincludedamount", -redBillItemset.getPao(i).getDouble("taxincludedamount"), 11L);
  203. i++;
  204. }
  205. return redBill.getUniqueIDValue();
  206. }
  207. public void createBlueInvoice() throws P2Exception {
  208. JSONObject contentObject = new JSONObject();
  209. JSONObject orderObject = new JSONObject();
  210. /**
  211. * 购方信息
  212. */
  213. PaoSetRemote tinvoiceapplySet = getPaoSet("tinvoiceapply");
  214. if (tinvoiceapplySet.isEmpty()) {
  215. throw new P2AppException("", "数据异常");
  216. }
  217. PaoRemote tinvoiceapply = tinvoiceapplySet.getPao(0);
  218. orderObject.put("buyerName", tinvoiceapply.getString("finvoicename"));//购方名称
  219. orderObject.put("buyerTaxNum", tinvoiceapply.getString("finvoicetaxnumber"));//购方税号(企业要填,个人可为空)
  220. orderObject.put("buyerTel", tinvoiceapply.getString("finvoicemobile"));//购方电话
  221. orderObject.put("buyerAddress", tinvoiceapply.getString("finvoiceaddress"));//购方地址
  222. orderObject.put("buyerAccount", tinvoiceapply.getString("finvoicebankandaccount"));//购方银行账号及开户行地址
  223. /**
  224. * 销方信息
  225. */
  226. orderObject.put("salerTaxNum", OpenApi.taxnum);//销方税号(使用沙箱环境请求时消息体参数salerTaxNum和消息头参数userTax填写339901999999142)
  227. orderObject.put("salerTel", "0573-89053728");//销方电话
  228. orderObject.put("salerAddress", "浙江省嘉兴市海盐县经济开发区棕榈路555号1#厂房");//销方地址
  229. orderObject.put("salerAccount", "中国银行股份有限公司海盐大桥新区支行370159618166");//销方银行账号和开户行地址
  230. orderObject.put("orderNo", String.valueOf(getUniqueIDValue()));//订单号(每个企业唯一)
  231. orderObject.put("invoiceDate", getDateTime_Str());//订单时间
  232. //orderObject.put("invoiceCode", "");//冲红时填写的对应蓝票发票代码(红票必填 10位或12 位, 11位的时候请左补 0)
  233. //orderObject.put("invoiceNum", "");//冲红时填写的对应蓝票发票号码(红票必填,不满8位请左补0)
  234. //orderObject.put("billInfoNo", "");//红字信息表编号.专票冲红时此项必填,且必须在备注中注明“开具红字增值税专用发票信息表编号ZZZZZZZZZZZZZZZZ”字样,其 中“Z”为开具红字增值税专用发票所需要的长度为16位信息表编号。
  235. //orderObject.put("departmentId", "");//部门门店id(诺诺系统中的id)
  236. //orderObject.put("clerkId", "");//开票员id(诺诺系统中的id)
  237. DBConnect dbConnect = new DBConnect();
  238. Rows rows = dbConnect.runSqlQuery("select fsonum = (stuff((select ',' + fsonum from (select distinct t3.fsonum from tinvoicebillitem t1\n" +
  239. "inner join tinvoiceapplyorder t2 on t1.siteid=t2.siteid and t1.tinvoiceapplyid=t2.tinvoiceapplyid and t1.tinvoiceapplyordid=t2.tinvoiceapplyordid\n" +
  240. "inner join saorder t3 on t2.siteid=t3.siteid and t2.saorderid=t3.saorderid \n" +
  241. "where t1.tinvoicebillid='" + getUniqueIDValue() + "' \n" +
  242. ")t for xml path('')),1,1,''))");
  243. String fnotes = getString("fnotes");
  244. String fsonum = rows.get(0).getString("fsonum");
  245. orderObject.put("remark", rows.isEmpty() ? fnotes : (fnotes.equals("") ? fsonum : (fnotes + ";" + fsonum)));//冲红时,在备注中注明“对应正数发票代码:XXXXXXXXX号码:YYYYYYYY”文案,其中“X”为发票代码,“Y”为发票号码,可以不填,接口会自动添加该文案;机动车发票蓝票时备注只能为空
  246. orderObject.put("checker", tinvoiceapply.getString("finvoicechecker"));//复核人
  247. orderObject.put("payee", tinvoiceapply.getString("finvoicepayee"));//收款人
  248. orderObject.put("clerk", tinvoiceapply.getString("finvoiceclerk"));//开票员
  249. //orderObject.put("listFlag", "0");//清单标志:非清单:0;清单:1,默认:0
  250. //orderObject.put("listName", "");//清单项目名称:对应发票票面项目名称(listFlag为1时,必填,默认为“详见销货清 单”)
  251. /**
  252. * 消息推送设置
  253. */
  254. String fphonenumber = tinvoiceapply.getString("fphonenumber");
  255. String femail = tinvoiceapply.getString("femail");
  256. String pushMode = "-1";
  257. if (!femail.equals("")) {
  258. if (!fphonenumber.equals("")) {
  259. pushMode = "2";
  260. } else {
  261. pushMode = "0";
  262. }
  263. } else {
  264. if (!fphonenumber.equals("")) {
  265. pushMode = "1";
  266. }
  267. }
  268. orderObject.put("pushMode", pushMode);//推送方式:-1,不推送;0,邮箱;1,手机(默认);2,邮箱、手机
  269. orderObject.put("buyerPhone", fphonenumber);//购方手机(pushMode为1或2时,此项为必填)
  270. orderObject.put("email", femail);//推送邮箱(pushMode为0或2时,此项为必填)
  271. orderObject.put("invoiceType", "1");//开票类型:1:蓝票;2:红票
  272. orderObject.put("invoiceLine", tinvoiceapply.getString("finvoiceline"));//发票种类:p,普通发票(电票)(默认);c,普通发票(纸票);s,专用发票;e,收购发票(电票);f,收购发票(纸质);r,普通发票(卷式);b,增值税 电子专用发票;j,机动车销售统一发票
  273. //orderObject.put("productOilFlag", "");//成品油标志:非成品油(默认):0;成品油:1
  274. //orderObject.put("proxyInvoiceFlag", "");//代开标志:0非代开;1代开。代开蓝票时备注要求填写文案:代开企业税号:***,代开企业名称:***;代开红票时备注要求填写文案:对应正数发票代码:***号码:***代开企业税号:***代开企业名称:***
  275. //orderObject.put("callBackUrl", "");//开票完成回传发票信息地址
  276. //orderObject.put("extensionNumber", "");//分机号(只能为空或者数字)
  277. //orderObject.put("terminalNumber", "");//终端号(开票终端号,只能 为空或数字)
  278. //orderObject.put("machineCode", "");//机器编号
  279. //orderObject.put("vehicleFlag", "");//是否机动车类专票 0-否 1-是
  280. JSONArray invoiceDetailArray = new JSONArray();
  281. PaoSetRemote tinvoicebillitemSet = getPaoSet("tinvoicebillitem");
  282. int i = 0;
  283. while (tinvoicebillitemSet.getPao(i) != null) {
  284. tinvoicebillitem tinvoicebillitem = (tinvoicebillitem) tinvoicebillitemSet.getPao(i);
  285. JSONObject invoiceDetailObject = new JSONObject();
  286. invoiceDetailObject.put("goodsName", tinvoicebillitem.getString("goodsname"));//商品名称(如invoiceLineProperty =1,则此商品行为折扣行,折扣行不允许多行折扣,折扣行必须紧邻被折扣行,商品名称必须与被折扣行一致)
  287. //invoiceDetailObject.put("goodsCode", "12312312312");//商品编码(商品税收分类编码开发者自行 填写)
  288. //invoiceDetailObject.put("selfCode", "");//自行编码(可不填)
  289. invoiceDetailObject.put("withTaxFlag", "1");//单价含税标志:0:不含税,1:含税
  290. invoiceDetailObject.put("price", String.valueOf(tinvoicebillitem.getDouble("price")));//单价,当单价(price)为空时,数量(num)也必须为空;(price)为空时,含税金额(ta xIncludedAmount)、不含税金额(taxEx cludedAmount)、税额(tax)都不能为空
  291. invoiceDetailObject.put("num", String.valueOf(tinvoicebillitem.getDouble("num")));//数量(开具红票时数量为负数)
  292. invoiceDetailObject.put("unit", String.valueOf(tinvoicebillitem.getString("unit")));//单位
  293. invoiceDetailObject.put("specType", String.valueOf(tinvoicebillitem.getString("spectype")));//规格型号
  294. //invoiceDetailObject.put("tax", "");//税额,[不含税金额] * [税率] = [税额];税额允许误差为 0.06。红票为负。不含税金额、税额、含税金额任何一个不传时,会 根据传入的单价,数量进行计算,可能和 实际数值存在误差,建议都传入
  295. invoiceDetailObject.put("taxRate", String.valueOf(tinvoicebillitem.getDouble("taxrate")));//税率,注:纸票清单红票存在为null的情况
  296. //invoiceDetailObject.put("taxExcludedAmount", "");//不含税金额。红票为负。不含税金额、税额、含税金额任何一个不传时,会根据传 入的单价,数量进行计算,可能和实际数 值存在误差,建议都传入
  297. //invoiceDetailObject.put("taxIncludedAmount", "");//含税金额,[不含税金额] + [税额] = [含税金额],红票为负。不含税金额、税额、含税金额任何一个不传时,会根据传入的单 价,数量进行计算,可能和实际数值存在 误差,建议都传入
  298. //invoiceDetailObject.put("invoiceLineProperty", "");//发票行性质:0,正常行;1,折扣行;2,被折扣行
  299. //invoiceDetailObject.put("favouredPolicyFlag", "");//优惠政策标识:0,不使用;1,使用
  300. //invoiceDetailObject.put("favouredPolicyName", "");//增值税特殊管理(优惠政策名称),当favouredPolicyFlag为1时,此项必填
  301. //invoiceDetailObject.put("deduction", "");//扣除额,差额征收时填写,目前只支持填写一项。 注意:当传0、空或字段不传时,都表示非差额征税;传0.00才表示差额 征税:0.00
  302. //invoiceDetailObject.put("zeroRateFlag", "");//零税率标识:空,非零税率;1,免税;2,不征税;3,普通零税率;1、当税率为:0%,且增 值税特殊管理:为“免税”, 零税率标识:需传“1” 2、当税率为:0%,且增值 税特殊管理:为"不征税" 零税率标识:需 传“2” 3、当税率为:0%,且增值税特 殊管理:为空 零税率标识:需传“3”
  303. invoiceDetailArray.add(invoiceDetailObject);
  304. i++;
  305. }
  306. orderObject.put("invoiceDetail", invoiceDetailArray);
  307. contentObject.put("order", orderObject);
  308. JSONObject result = new OpenApi().requestApi("nuonuo.ElectronInvoice.requestBillingNew", contentObject.toString());
  309. if (result.containsKey("code") && result.getString("code").equalsIgnoreCase("E0000")) {
  310. String invoiceSerialNum = result.getJSONObject("result").getString("invoiceSerialNum");
  311. setValue("finvoiceserialnum", invoiceSerialNum, 11L);
  312. }
  313. if (result.containsKey("describe")) {
  314. String describe = result.getString("describe");
  315. setValue("msg", describe, 11L);
  316. }
  317. }
  318. public void createRedInvoice() throws P2Exception {
  319. PaoSetRemote tinvoicebill_blueSet = getPaoSet("tinvoicebill_blue");
  320. if (tinvoicebill_blueSet.isEmpty()) {
  321. throw new P2AppException("", "找不到对应到蓝票信息");
  322. }
  323. JSONObject contentObject = new JSONObject();
  324. JSONObject orderObject = new JSONObject();
  325. /**
  326. * 购方信息
  327. */
  328. PaoSetRemote tinvoiceapplySet = getPaoSet("tinvoiceapply");
  329. if (tinvoiceapplySet.isEmpty()) {
  330. throw new P2AppException("", "数据异常");
  331. }
  332. PaoRemote tinvoiceapply = tinvoiceapplySet.getPao(0);
  333. orderObject.put("buyerName", tinvoiceapply.getString("finvoicename"));//购方名称
  334. orderObject.put("buyerTaxNum", tinvoiceapply.getString("finvoicetaxnumber"));//购方税号(企业要填,个人可为空)
  335. orderObject.put("buyerTel", tinvoiceapply.getString("finvoicemobile"));//购方电话
  336. orderObject.put("buyerAddress", tinvoiceapply.getString("finvoiceaddress"));//购方地址
  337. orderObject.put("buyerAccount", tinvoiceapply.getString("finvoicebankandaccount"));//购方银行账号及开户行地址
  338. /**
  339. * 销方信息
  340. */
  341. orderObject.put("salerTaxNum", OpenApi.taxnum);//销方税号(使用沙箱环境请求时消息体参数salerTaxNum和消息头参数userTax填写339901999999142)
  342. orderObject.put("salerTel", "0573-89053728");//销方电话
  343. orderObject.put("salerAddress", "浙江省嘉兴市海盐县经济开发区棕榈路555号1#厂房");//销方地址
  344. orderObject.put("salerAccount", "中国银行股份有限公司海盐大桥新区支行370159618166");//销方银行账号和开户行地址
  345. orderObject.put("orderNo", String.valueOf(getUniqueIDValue()));//订单号(每个企业唯一)
  346. orderObject.put("invoiceDate", getDateTime_Str());//订单时间
  347. PaoRemote tinvoicebill_blue = tinvoicebill_blueSet.getPao(0);
  348. String invoicecode = tinvoicebill_blue.getString("invoicecode");
  349. if (invoicecode.length() == 11) {
  350. invoicecode = "0" + invoicecode;
  351. }
  352. orderObject.put("invoiceCode", invoicecode);//冲红时填写的对应蓝票发票代码(红票必填 10位或12 位, 11位的时候请左补 0)
  353. orderObject.put("invoiceNum", createstr(8, tinvoicebill_blue.getString("invoiceNo")));//冲红时填写的对应蓝票发票号码(红票必填,不满8位请左补0)
  354. DBConnect dbConnect = new DBConnect();
  355. if (tinvoiceapply.getString("finvoiceline").equals("s") || tinvoiceapply.getString("finvoiceline").equals("b")) {
  356. orderObject.put("billInfoNo", getString("billInfoNo"));//红字信息表编号.专票冲红时此项必填,且必须在备注中注明“开具红字增值税专用发票信息表编号ZZZZZZZZZZZZZZZZ”字样,其 中“Z”为开具红字增值税专用发票所需要的长度为16位信息表编号。
  357. orderObject.put("remark", "开具红字增值税专用发票信息表编号" + getString("billInfoNo"));//冲红时,在备注中注明“对应正数发票代码:XXXXXXXXX号码:YYYYYYYY”文案,其中“X”为发票代码,“Y”为发票号码,可以不填,接口会自动添加该文案;机动车发票蓝票时备注只能为空
  358. }
  359. //orderObject.put("departmentId", "");//部门门店id(诺诺系统中的id)
  360. //orderObject.put("clerkId", "");//开票员id(诺诺系统中的id)
  361. //tinvoicebillitem
  362. orderObject.put("checker", tinvoiceapply.getString("finvoicechecker"));//复核人
  363. orderObject.put("payee", tinvoiceapply.getString("finvoicepayee"));//收款人
  364. orderObject.put("clerk", tinvoiceapply.getString("finvoiceclerk"));//开票员
  365. //orderObject.put("listFlag", "0");//清单标志:非清单:0;清单:1,默认:0
  366. //orderObject.put("listName", "");//清单项目名称:对应发票票面项目名称(listFlag为1时,必填,默认为“详见销货清 单”)
  367. /**
  368. * 消息推送设置
  369. */
  370. String fphonenumber = tinvoiceapply.getString("fphonenumber");
  371. String femail = tinvoiceapply.getString("femail");
  372. String pushMode = "-1";
  373. if (!femail.equals("")) {
  374. if (!fphonenumber.equals("")) {
  375. pushMode = "2";
  376. } else {
  377. pushMode = "0";
  378. }
  379. } else {
  380. if (!fphonenumber.equals("")) {
  381. pushMode = "1";
  382. }
  383. }
  384. orderObject.put("pushMode", pushMode);//推送方式:-1,不推送;0,邮箱;1,手机(默认);2,邮箱、手机
  385. orderObject.put("buyerPhone", fphonenumber);//购方手机(pushMode为1或2时,此项为必填)
  386. orderObject.put("email", femail);//推送邮箱(pushMode为0或2时,此项为必填)
  387. orderObject.put("invoiceType", "2");//开票类型:1:蓝票;2:红票
  388. orderObject.put("invoiceLine", tinvoiceapply.getString("finvoiceline"));//发票种类:p,普通发票(电票)(默认);c,普通发票(纸票);s,专用发票;e,收购发票(电票);f,收购发票(纸质);r,普通发票(卷式);b,增值税 电子专用发票;j,机动车销售统一发票
  389. //orderObject.put("productOilFlag", "");//成品油标志:非成品油(默认):0;成品油:1
  390. //orderObject.put("proxyInvoiceFlag", "");//代开标志:0非代开;1代开。代开蓝票时备注要求填写文案:代开企业税号:***,代开企业名称:***;代开红票时备注要求填写文案:对应正数发票代码:***号码:***代开企业税号:***代开企业名称:***
  391. //orderObject.put("callBackUrl", "");//开票完成回传发票信息地址
  392. //orderObject.put("extensionNumber", "");//分机号(只能为空或者数字)
  393. //orderObject.put("terminalNumber", "");//终端号(开票终端号,只能 为空或数字)
  394. //orderObject.put("machineCode", "");//机器编号
  395. //orderObject.put("vehicleFlag", "");//是否机动车类专票 0-否 1-是
  396. JSONArray invoiceDetailArray = new JSONArray();
  397. PaoSetRemote tinvoicebillitemSet = getPaoSet("tinvoicebillitem");
  398. int i = 0;
  399. while (tinvoicebillitemSet.getPao(i) != null) {
  400. tinvoicebillitem tinvoicebillitem = (tinvoicebillitem) tinvoicebillitemSet.getPao(i);
  401. JSONObject invoiceDetailObject = new JSONObject();
  402. invoiceDetailObject.put("goodsName", tinvoicebillitem.getString("goodsname"));//商品名称(如invoiceLineProperty =1,则此商品行为折扣行,折扣行不允许多行折扣,折扣行必须紧邻被折扣行,商品名称必须与被折扣行一致)
  403. //invoiceDetailObject.put("goodsCode", "12312312312");//商品编码(商品税收分类编码开发者自行 填写)
  404. //invoiceDetailObject.put("selfCode", "");//自行编码(可不填)
  405. invoiceDetailObject.put("withTaxFlag", "1");//单价含税标志:0:不含税,1:含税
  406. invoiceDetailObject.put("price", String.valueOf(tinvoicebillitem.getDouble("price")));//单价,当单价(price)为空时,数量(num)也必须为空;(price)为空时,含税金额(ta xIncludedAmount)、不含税金额(taxEx cludedAmount)、税额(tax)都不能为空
  407. invoiceDetailObject.put("num", String.valueOf(tinvoicebillitem.getDouble("num")));//数量(开具红票时数量为负数)
  408. invoiceDetailObject.put("unit", String.valueOf(tinvoicebillitem.getString("unit")));//单位
  409. invoiceDetailObject.put("specType", String.valueOf(tinvoicebillitem.getString("spectype")));//规格型号
  410. //invoiceDetailObject.put("tax", "");//税额,[不含税金额] * [税率] = [税额];税额允许误差为 0.06。红票为负。不含税金额、税额、含税金额任何一个不传时,会 根据传入的单价,数量进行计算,可能和 实际数值存在误差,建议都传入
  411. invoiceDetailObject.put("taxRate", String.valueOf(tinvoicebillitem.getDouble("taxrate")));//税率,注:纸票清单红票存在为null的情况
  412. //invoiceDetailObject.put("taxExcludedAmount", "");//不含税金额。红票为负。不含税金额、税额、含税金额任何一个不传时,会根据传 入的单价,数量进行计算,可能和实际数 值存在误差,建议都传入
  413. //invoiceDetailObject.put("taxIncludedAmount", "");//含税金额,[不含税金额] + [税额] = [含税金额],红票为负。不含税金额、税额、含税金额任何一个不传时,会根据传入的单 价,数量进行计算,可能和实际数值存在 误差,建议都传入
  414. //invoiceDetailObject.put("invoiceLineProperty", "");//发票行性质:0,正常行;1,折扣行;2,被折扣行
  415. //invoiceDetailObject.put("favouredPolicyFlag", "");//优惠政策标识:0,不使用;1,使用
  416. //invoiceDetailObject.put("favouredPolicyName", "");//增值税特殊管理(优惠政策名称),当favouredPolicyFlag为1时,此项必填
  417. //invoiceDetailObject.put("deduction", "");//扣除额,差额征收时填写,目前只支持填写一项。 注意:当传0、空或字段不传时,都表示非差额征税;传0.00才表示差额 征税:0.00
  418. //invoiceDetailObject.put("zeroRateFlag", "");//零税率标识:空,非零税率;1,免税;2,不征税;3,普通零税率;1、当税率为:0%,且增 值税特殊管理:为“免税”, 零税率标识:需传“1” 2、当税率为:0%,且增值 税特殊管理:为"不征税" 零税率标识:需 传“2” 3、当税率为:0%,且增值税特 殊管理:为空 零税率标识:需传“3”
  419. invoiceDetailArray.add(invoiceDetailObject);
  420. i++;
  421. }
  422. orderObject.put("invoiceDetail", invoiceDetailArray);
  423. contentObject.put("order", orderObject);
  424. JSONObject result = new OpenApi().requestApi("nuonuo.ElectronInvoice.requestBillingNew", contentObject.toString());
  425. if (result.containsKey("code") && result.getString("code").equalsIgnoreCase("E0000")) {
  426. String invoiceSerialNum = result.getJSONObject("result").getString("invoiceSerialNum");
  427. setValue("finvoiceserialnum", invoiceSerialNum, 11L);
  428. }
  429. if (result.containsKey("describe")) {
  430. String describe = result.getString("describe");
  431. setValue("msg", describe, 11L);
  432. }
  433. }
  434. private String createstr(int length, String str) {
  435. // 长度
  436. if (length > str.length()) {
  437. str = String.format("%0" + (length) + "d", Long.parseLong(str));
  438. }
  439. return str;
  440. }
  441. /**
  442. * 将发票下载到本地
  443. *
  444. * @param urlstr
  445. * @return
  446. */
  447. public void upLoadDocUrl(String urlstr, String description) {
  448. String doctype = "Attachments";
  449. try {
  450. String str = urlstr.substring(urlstr.lastIndexOf("/") + 1);
  451. ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
  452. try {
  453. URL url = new URL(urlstr);
  454. HttpURLConnection httpUrl = (HttpURLConnection) url.openConnection();
  455. httpUrl.connect();
  456. BufferedInputStream bis = new BufferedInputStream(httpUrl.getInputStream());
  457. byte[] arrayOfByte = new byte[4096];
  458. int i;
  459. while (-1 != (i = bis.read(arrayOfByte))) {
  460. byteArrayOutputStream.write(arrayOfByte, 0, i);
  461. }
  462. } catch (IOException iOException) {
  463. }
  464. UploadFile uploadFile = new UploadFile(str, "image\\png", byteArrayOutputStream);
  465. Properties properties = P2Server.getP2Server().getConfig();
  466. StringBuffer stringBuffer = new StringBuffer(properties.getProperty("p2.attachment.defaultpath"));
  467. String str1 = properties.getProperty("p2.attachment.ostype");
  468. String str2 = "";
  469. PaoSetRemote ps_sysvarsSet = P2Server.getP2Server().getPaoSet("PS_SYSVARS", P2Server.getP2Server().getSystemUserInfo());
  470. ps_sysvarsSet.setWhere("varname='DOCUMENT_DIR_RULE'");
  471. ps_sysvarsSet.reset();
  472. if (!ps_sysvarsSet.isEmpty()) {
  473. String[] arrayOfString = ps_sysvarsSet.getPao(0).getString("varvalue")
  474. .split("[/]");
  475. stringBuffer.append(File.separator + getString("siteid"));
  476. str2 = str2 + getString("siteid") + "/";
  477. for (byte b = 1; b < arrayOfString.length; b++) {
  478. if ("DOCTYPE".equalsIgnoreCase(arrayOfString[b])) {
  479. stringBuffer.append(File.separator + doctype);
  480. str2 = str2 + doctype + "/";
  481. } else if ("TABLE".equalsIgnoreCase(arrayOfString[b])) {
  482. stringBuffer.append(File.separator + getName().toUpperCase());
  483. str2 = str2 + getName().toUpperCase() + "/";
  484. }
  485. }
  486. }
  487. ps_sysvarsSet.close();
  488. String str3 = stringBuffer.toString();
  489. String filename = uploadFile.getFileName();
  490. String filetype = filename.substring(filename.lastIndexOf(".") + 1);
  491. //filename = "url附件";
  492. try {
  493. uploadFile.setDirectoryName(str3);
  494. uploadFile.writeToDisk();
  495. str3 = uploadFile.getAbsoluteFileName();
  496. File file = new File(str3);
  497. if (str1 != null && !Utility.isNull(str1.trim()) && str1.trim().equalsIgnoreCase("OSS")) {
  498. UploadFileOSS uploadFileOSS;
  499. (uploadFileOSS = new UploadFileOSS(str3, uploadFile.getFileName(), "", str2)).writeOSS();
  500. if (file.exists() && file.isFile()) {
  501. file.delete();
  502. }
  503. }
  504. if (!Utility.isNull(str3)) {
  505. uploadFile.save();
  506. }
  507. } catch (IOException iOException) {
  508. }
  509. str3 = uploadFile.getFileName();
  510. PaoRemote paoRemote;
  511. PaoSetRemote paoSetRemote3;
  512. (paoRemote = (paoSetRemote3 = P2Server.getP2Server().getPaoSet("DOCINFO", P2Server.getP2Server().getSystemUserInfo())).add())
  513. .setValue("document", filename, 11L);
  514. paoRemote.setValue("ownertable", getName().toUpperCase(), 11L);
  515. paoRemote.setValue("description", description, 11L);
  516. paoRemote.setValue("postfix", filetype, 11L);
  517. paoRemote.setValue("doctype", doctype, 11L);
  518. paoRemote.setValue("serialnumber", str3, 11L);
  519. paoRemote.setValue("siteid", getString("siteid"), 11L);
  520. paoSetRemote3.save();
  521. PaoSetRemote paoSetRemote1;
  522. if ((paoSetRemote1 = paoRemote.getPaoSet("DOCLINKS")).isEmpty()) {
  523. PaoRemote paoRemote1;
  524. (paoRemote1 = paoSetRemote1.add()).setValue("document", filename, 11L);
  525. paoRemote1.setValue("docinfoid", paoRemote.getLong("docinfoid"), 11L);
  526. paoRemote1.setValue("ownertable", getName().toUpperCase(), 11L);
  527. paoRemote1.setValue("DOCTYPE", doctype, 11L);
  528. paoRemote1.setValue("description", description, 11L);
  529. paoRemote1.setValue("OWNERID", getUniqueIDValue(), 11L);
  530. paoSetRemote1.save();
  531. paoSetRemote1 = paoRemote1.getPaoSet("$DOCHISTORY", "DOCHISTORY", "");
  532. ((Doclinks) paoRemote1).addDochistory(paoSetRemote1, "Add");
  533. paoSetRemote1.save();
  534. }
  535. paoSetRemote3.close();
  536. } catch (Exception exception) {
  537. exception.printStackTrace();
  538. }
  539. }
  540. // public static void main(String[] args) throws Exception {
  541. // tinvoicebill tinvoicebill = new tinvoicebill(null);
  542. // String a = tinvoicebill.createPrintStr("3300062620", "00848776", 220);
  543. // System.err.println(a);
  544. // }
  545. public void createPrintStr(String FPDM, String FPHM, double famount) {
  546. String printstr = "";
  547. try {
  548. //明文
  549. String content = "01!" + FPDM + "!" + FPHM + "!" + famount;
  550. //AES密文
  551. String aes = aesEncryptC(content, "0ozSri9LpPvz0f6H");
  552. String pub = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQClj0t1b+O5Cq06d0yp4qZHM3OhNSmoaArC6qAhehT/DB23F/CCUSFrQCjADhOvCq+xu4JcNGQ1kpjhKVNb642QPlSDJ04QM/+3mKcu/WKLDZ+3zQYvNY41pcjTyxtUT9ixaBx8OQQfOp+qiAYYBtE9T6WRLCrl1YN0drpDvFylyQIDAQAB";
  553. //Rsa密文
  554. //System.out.println("公钥加密:" + encrypt(aes, getPublickey(pub)));
  555. //示例
  556. String rsa = URLEncoder.encode(OpenApi.taxnum + "!" + encrypt(aes, getPublickey(pub)) + "!01", "UTF-8");
  557. printstr = "<a href=webprint:\"0," + rsa + "> 发票打印 </a>";
  558. setValue("fprintparameter", printstr, 11L);
  559. } catch (Exception e) {
  560. e.printStackTrace();
  561. }
  562. }
  563. /**
  564. * RSA最大加密明文大小
  565. */
  566. private static final int MAX_ENCRYPT_BLOCK = 117;
  567. /**
  568. * RSA最大解密密文大小
  569. */
  570. private static final int MAX_DECRYPT_BLOCK = 128;
  571. /**
  572. * 默认字符集编码
  573. */
  574. private static final String DEFAULT_CHARSET = "UTF-8";
  575. /**
  576. * RSA加密
  577. *
  578. * @param data 待加密数据
  579. * @param publicKey 公钥
  580. * @return
  581. * @author pcheng
  582. * @date 2018-6-25
  583. */
  584. public static String encrypt(String data, PublicKey publicKey) throws Exception {
  585. Cipher cipher = Cipher.getInstance("RSA");
  586. cipher.init(Cipher.ENCRYPT_MODE, publicKey);
  587. int inputLen = data.getBytes(DEFAULT_CHARSET).length;
  588. ByteArrayOutputStream out = new ByteArrayOutputStream();
  589. int offSet = 0;
  590. byte[] cache;
  591. int i = 0;
  592. // 对数据分段加密
  593. while (inputLen - offSet > 0) {
  594. if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
  595. cache = cipher.doFinal(data.getBytes(DEFAULT_CHARSET), offSet, MAX_ENCRYPT_BLOCK);
  596. } else {
  597. cache = cipher.doFinal(data.getBytes(DEFAULT_CHARSET), offSet, inputLen - offSet);
  598. }
  599. out.write(cache, 0, cache.length);
  600. i++;
  601. offSet = i * MAX_ENCRYPT_BLOCK;
  602. }
  603. byte[] encryptedData = out.toByteArray();
  604. out.close();
  605. /*获取加密内容以UTF-8为标准转化的字节进行加密后再使用base64编码成字符串*/
  606. /*加密后的字符串*/
  607. return Base64.encodeBase64String(encryptedData);
  608. }
  609. /**
  610. * 获取公钥
  611. *
  612. * @param publicKey 公钥字符串
  613. * @return 公钥对象
  614. * @throws Exception
  615. */
  616. public static PublicKey getPublickey(String publicKey) throws Exception {
  617. KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  618. X509EncodedKeySpec bobPubKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey.getBytes()));
  619. return keyFactory.generatePublic(bobPubKeySpec);
  620. }
  621. /**
  622. * AES加密 ECB加密
  623. *
  624. * @param encryptStr 待加密的base 64 code
  625. * @param decryptKey 加密密钥
  626. * @return 加密后的string
  627. * @throws Exception
  628. */
  629. public static String aesEncryptC(String encryptStr, String decryptKey) throws Exception {
  630. return parseByte2HexStr(aesEncryptToBytesC(encryptStr, decryptKey));
  631. }
  632. /**
  633. * AES加密 ECB
  634. *
  635. * @param content 待加密的内容
  636. * @param encryptKey 加密密钥
  637. * @return 加密后的byte[]
  638. * @throws Exception
  639. */
  640. private static byte[] aesEncryptToBytesC(String content, String encryptKey) {
  641. try {
  642. Cipher aesECB = Cipher.getInstance("AES/ECB/PKCS5Padding");
  643. SecretKeySpec key = new SecretKeySpec(encryptKey.getBytes(), "AES");
  644. aesECB.init(Cipher.ENCRYPT_MODE, key);
  645. byte[] result = aesECB.doFinal(content.getBytes("UTF-8"));
  646. return result;
  647. } catch (Exception e) {
  648. throw new RuntimeException(e.getMessage());
  649. }
  650. }
  651. /**
  652. * 将二进制转换成16进制
  653. *
  654. * @param buf
  655. * @return
  656. */
  657. private static String parseByte2HexStr(byte[] buf) {
  658. StringBuffer sb = new StringBuffer();
  659. if (buf == null) {
  660. return sb.toString();
  661. }
  662. for (int i = 0; i < buf.length; i++) {
  663. String hex = Integer.toHexString(buf[i] & 0xFF);
  664. if (hex.length() == 1) {
  665. hex = '0' + hex;
  666. }
  667. sb.append(hex.toUpperCase());
  668. }
  669. return sb.toString();
  670. }
  671. @Override
  672. public void fieldValidate(Object paoField, String fieldname) throws P2Exception {
  673. super.fieldValidate(paoField, fieldname);
  674. }
  675. @Override
  676. public void fieldAction(Object paoField, String fieldname) throws P2Exception {
  677. super.fieldAction(paoField, fieldname);
  678. }
  679. }