InvoiceApplyService.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. package com.pj.api.invoice.service;
  2. import cn.hutool.core.bean.BeanUtil;
  3. import cn.hutool.core.codec.Base64;
  4. import cn.hutool.core.date.DateUtil;
  5. import cn.hutool.core.lang.Snowflake;
  6. import cn.hutool.core.util.IdUtil;
  7. import cn.hutool.core.util.StrUtil;
  8. import cn.hutool.http.HttpUtil;
  9. import cn.hutool.json.JSON;
  10. import cn.hutool.json.JSONArray;
  11. import cn.hutool.json.JSONObject;
  12. import cn.hutool.json.JSONUtil;
  13. import com.pj.api.invoice.bo.InvoiceApply;
  14. import com.pj.api.invoice.bo.InvoiceApplyCallBackSub;
  15. import com.pj.api.invoice.bo.InvoiceApplySub;
  16. import com.pj.api.invoice.bo.InvoiceApplySubDetail;
  17. import com.pj.api.invoice.utils.InvoiceUtils;
  18. import com.pj.api.wx.bo.Attach;
  19. import com.pj.api.wx.bo.PriceBO;
  20. import com.pj.current.config.InvoiceConfig;
  21. import com.pj.project.tb_fee_details.TbFeeDetails;
  22. import com.pj.project.tb_fee_details.TbFeeDetailsService;
  23. import com.pj.project.tb_fee_statistics.TbFeeStatistics;
  24. import com.pj.project.tb_invoice_details.TbInvoiceDetails;
  25. import com.pj.project.tb_invoice_details.TbInvoiceDetailsService;
  26. import com.pj.project.tb_invoice_info.TbInvoiceInfo;
  27. import com.pj.project.tb_invoice_info.TbInvoiceInfoService;
  28. import com.pj.project.tb_invoice_info.dto.FeeDeatilsGroup;
  29. import com.pj.project.tb_invoice_order.TbInvoiceOrder;
  30. import com.pj.project.tb_invoice_order.TbInvoiceOrderService;
  31. import com.pj.project.tb_order.TbOrder;
  32. import com.pj.project.tb_order.TbOrderService;
  33. import com.pj.project4sp.global.BusinessException;
  34. import com.pj.utils.sg.AjaxError;
  35. import com.pj.utils.so.SoMap;
  36. import lombok.extern.slf4j.Slf4j;
  37. import org.springframework.scheduling.annotation.Async;
  38. import org.springframework.stereotype.Service;
  39. import org.springframework.transaction.annotation.Transactional;
  40. import javax.annotation.Resource;
  41. import java.math.BigDecimal;
  42. import java.util.*;
  43. import java.util.stream.Collectors;
  44. /**
  45. * Created with IntelliJ IDEA.
  46. *
  47. * @Auther: lzm
  48. * @Date: 2022/08/09/14:51
  49. * @Description:
  50. */
  51. @Service
  52. @Transactional
  53. @Slf4j
  54. public class InvoiceApplyService {
  55. @Resource
  56. TbInvoiceDetailsService tbInvoiceDetailsService;
  57. @Resource
  58. TbInvoiceInfoService tbInvoiceInfoService;
  59. @Resource
  60. TbInvoiceOrderService tbInvoiceOrderService;
  61. @Resource
  62. TbFeeDetailsService tbFeeDetailsService;
  63. @Resource
  64. InvoiceConfig invoiceConfig;
  65. public String applyInvoice(String infoId) {
  66. String code = this.preApply(infoId);
  67. if (!StrUtil.equals("200", code)) {
  68. throw new BusinessException("开票申请推送失败!");
  69. }
  70. return code;
  71. }
  72. public String preApply(String infoId) {
  73. Date now = new Date();
  74. Map<String, String> param = new HashMap<>();
  75. param.put("action", invoiceConfig.getApplyAction());
  76. param.put("appid", invoiceConfig.getAppId());
  77. param.put("timestamp", InvoiceUtils.date2StrByInt(now, "yyyyMMddHHmmssFFF"));
  78. param.put("transid", InvoiceUtils.genTransId());
  79. String sign = InvoiceUtils.createSign(InvoiceUtils.getSortedMap(param), invoiceConfig.getAppSecret());
  80. param.put("sign", sign);
  81. //拼装请求url
  82. String url = InvoiceUtils.getUrl(invoiceConfig.getApplyUrl(), param);
  83. TbInvoiceInfo info = tbInvoiceInfoService.getById(infoId);
  84. List<TbInvoiceDetails> invoiceDetails = tbInvoiceDetailsService.findByInfoId(infoId);
  85. //开始组装接口参数
  86. InvoiceApply invoiceApply = new InvoiceApply();
  87. invoiceApply.setRequestId(now.getTime() + "")
  88. .setBusinessSystemCode("SW_TEST")
  89. .setInterfaceCode("BILL.PUSH");
  90. List<InvoiceApplySub> applys = new ArrayList<>();
  91. for (TbInvoiceDetails invoiceDetail : invoiceDetails) {
  92. InvoiceApplySub apply = new InvoiceApplySub();
  93. apply.setBillNo(invoiceDetail.getId()).setPayType("微信支付")
  94. .setBillDate(DateUtil.format(now, "yyyy-MM-dd"))
  95. .setTotalAmount(invoiceDetail.getMoney()).setIncludeTaxFlag(1)
  96. .setAutoInvoice(1).setAutoMerge(1)
  97. .setInvoiceType("026")
  98. .setBuyerName(info.getEntityName()).setBuyerTaxpayerId(info.getTaxIdNo())
  99. .setBuyerRecipientMail(info.getEmail())
  100. .setBuyerProperty(0)
  101. .setBuyerBankAndAccount(info.getBank() + info.getBankNo())
  102. .setTextField1(info.getCustomerName())
  103. .setSellerName(invoiceConfig.getSellerName())
  104. .setSellerTaxpayerId(invoiceConfig.getSellerTaxpayerId())
  105. .setTaxationStyle(0)
  106. .setDrawer(invoiceConfig.getDrawer())
  107. .setPayee(invoiceConfig.getPayee()).setReviewer(invoiceConfig.getReviewer());
  108. //将所有开票订单的收费明细放在一个集合中,并对其分组
  109. List<TbInvoiceOrder> orders = tbInvoiceOrderService.findByDetailId(invoiceDetail.getId());
  110. List<FeeDeatilsGroup> feeDetailsGroupList = grouping(orders);
  111. List<InvoiceApplySubDetail> applyDetails = new ArrayList<>();
  112. Snowflake snowflake = IdUtil.getSnowflake(1, 1);
  113. for (FeeDeatilsGroup group : feeDetailsGroupList) {
  114. String detailId = snowflake.nextIdStr();
  115. InvoiceApplySubDetail applyDetail = new InvoiceApplySubDetail();
  116. applyDetail.setAmount(group.getItemPrice())
  117. .setDetailId(detailId)
  118. .setGoodsName(group.getItemTypeName())
  119. .setLineProperty(2)
  120. .setQuantity(group.getNum())
  121. .setPrice(group.getUnitPrice())
  122. .setTaxRate(group.getTaxRate().toString());
  123. if (StrUtil.equals("0.09", applyDetail.getTaxRate())) {
  124. applyDetail.setRevenueCode(invoiceConfig.getCarTaxRateCode());
  125. } else {
  126. applyDetail.setRevenueCode(invoiceConfig.getBusinessTaxRateCode());
  127. }
  128. applyDetails.add(applyDetail);
  129. }
  130. apply.setBillDetail(applyDetails);
  131. applys.add(apply);
  132. }
  133. log.info("invoice apply url:" + url);
  134. String applysJson = JSONUtil.toJsonStr(applys);
  135. log.info("invoice apply data:" + applysJson);
  136. String applysBase64 = Base64.encode(applysJson);
  137. invoiceApply.setData(applysBase64);
  138. String paramStr = JSONUtil.toJsonStr(invoiceApply);
  139. log.info("invoice apply paramStr:" + paramStr);
  140. String result = HttpUtil.createPost(url).header("Content-Type", "application/json").body(paramStr).execute().body();
  141. log.info("invoice apply result:" + result);
  142. JSONObject jsonResult = JSONUtil.parseObj(result);
  143. if (StrUtil.equals("0", jsonResult.getStr("code"))) {
  144. info.setApplyAble(1).setStatus(2);
  145. tbInvoiceInfoService.updateById(info);
  146. return "200";
  147. } else {
  148. throw new AjaxError("开票失败");
  149. }
  150. }
  151. private List<FeeDeatilsGroup> grouping(List<TbInvoiceOrder> invoiceOrderList) {
  152. List<TbFeeDetails> feeDetailsList = new ArrayList<>();
  153. for (TbInvoiceOrder invoiceOrder : invoiceOrderList) {
  154. List<TbFeeDetails> detailsList = tbFeeDetailsService.findByTransactionId(invoiceOrder.getTransactionId());
  155. feeDetailsList.addAll(detailsList);
  156. }
  157. List<FeeDeatilsGroup> list = new ArrayList<>();
  158. for (TbFeeDetails detail : feeDetailsList) {
  159. FeeDeatilsGroup group = new FeeDeatilsGroup();
  160. BeanUtil.copyProperties(detail, group);
  161. String hash = (detail.getItemTypeName() + detail.getUnitPrice()).hashCode() + "";
  162. group.setGroupHash(hash);
  163. list.add(group);
  164. }
  165. Map<String, List<FeeDeatilsGroup>> collect = list.stream()
  166. .collect(Collectors.groupingBy(FeeDeatilsGroup::getGroupHash));
  167. List<FeeDeatilsGroup> completeGroups = new ArrayList<>();
  168. for (String key : collect.keySet()) {
  169. List<FeeDeatilsGroup> partGroups = collect.get(key);
  170. FeeDeatilsGroup realGroup = new FeeDeatilsGroup();
  171. realGroup.setItemTypeName(partGroups.get(0).getItemTypeName())
  172. .setUnitPrice(partGroups.get(0).getUnitPrice())
  173. .setTaxRate(partGroups.get(0).getTaxRate());
  174. for (FeeDeatilsGroup partGroup : partGroups) {
  175. realGroup.setItemPrice(realGroup.getItemPrice().add(partGroup.getItemPrice()))
  176. .setNoTaxPrice(realGroup.getNoTaxPrice().add(partGroup.getNoTaxPrice()))
  177. .setTaxPrice(realGroup.getTaxPrice().add(partGroup.getTaxPrice()))
  178. .setNum(realGroup.getNum() + partGroup.getNum());
  179. }
  180. completeGroups.add(realGroup);
  181. }
  182. return completeGroups;
  183. }
  184. public synchronized Map<String, Object> callBack(String sub) {
  185. log.info("进入开票回调:");
  186. Map<String, Object> map = new LinkedHashMap<>();
  187. JSONObject jsonObject = JSONUtil.parseObj(sub);
  188. InvoiceApplyCallBackSub callBackSub = JSONUtil.toBean(jsonObject, InvoiceApplyCallBackSub.class);
  189. TbInvoiceDetails invoiceDetail = tbInvoiceDetailsService.getById(callBackSub.getBillNo());
  190. if (invoiceDetail == null) {
  191. log.info("开票信息子记录{}不存在:", callBackSub.getBillNo());
  192. map.put("code", 500);
  193. map.put("message", "失败,开票信息数据异常");
  194. return map;
  195. }
  196. if (invoiceDetail.getIsApply() == 2) {
  197. log.info("重复回调,开票信息子记录{}已开票成功:", callBackSub.getBillNo());
  198. } else {
  199. invoiceDetail.setIsApply(2).setInvoiceNo(callBackSub.getInvoiceNum())
  200. .setInvoiceCode(callBackSub.getInvoiceCode())
  201. .setFileUrl(callBackSub.getInvoiceFileUrl()).setImageUrl(callBackSub.getInvoiceImageUrl());
  202. tbInvoiceDetailsService.updateById(invoiceDetail);
  203. TbInvoiceInfo info = tbInvoiceInfoService.getById(invoiceDetail.getInfoId());
  204. // List<TbInvoiceDetails> infoAllDetails = tbInvoiceDetailsService.findByInfoId(info.getId());
  205. // String newInvoiceNo = "";
  206. // for (TbInvoiceDetails detail : infoAllDetails) {
  207. // newInvoiceNo = StrUtil.isEmpty(newInvoiceNo) ?
  208. // detail.getInvoiceNo() : newInvoiceNo+","+detail.getInvoiceNo();
  209. // }
  210. String status = callBackSub.getInvoiceStatus();
  211. if ("0".equals(status)) {
  212. //开票成功
  213. info.setStatus(1);
  214. info.setIsApply(2);
  215. } else if ("".equals(status)){
  216. info.setStatus(Integer.parseInt(status));
  217. }
  218. tbInvoiceInfoService.updateById(info);
  219. String oldInvoiceNo = info.getInvoiceNo();
  220. String newInvoiceNo = StrUtil.isEmpty(oldInvoiceNo) ?
  221. callBackSub.getInvoiceNum() : oldInvoiceNo + "," + callBackSub.getInvoiceNum();
  222. SoMap so = new SoMap();
  223. so.put("id", info.getId());
  224. so.put("invoiceTime", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
  225. so.put("invoiceNo", newInvoiceNo);
  226. tbInvoiceInfoService.complete(so);
  227. }
  228. map.put("code", 200);
  229. map.put("message", "成功");
  230. return map;
  231. }
  232. }