上一篇文章搭建了开票中间平台B,下一步平台C调用开票平台B业务流程
一、开票系统调用流程
- 首先,调用平台C须提前注册到开票平台B,获取到对应的clientId,clientSecret。注册信息包括回要回调的地址callBackUrl(开票成功或失败回调使用);
-
业务流程图如下
开票系统流程图.png - 调用平台C 获取token,缓存在redis中
/**
* 获取开放平台Token
* @return
*/
private String getOpenToken(String redisKey) {
String accessToken = (String) redisUtil.get(redisKey);
if (StringUtils.isNotBlank(accessToken)) {
return accessToken;
}
//获取token Url
StringBuilder reqUrl = new StringBuilder();
reqUrl.append(url + OpenInvoiceConstant.ACCESS_TOKEN_URL);
reqUrl.append("?client_id=").append(clientId);
reqUrl.append("&client_secret=").append(clientSecret);
AjaxResponse
- 调用开票平台B 开票接口
/**
* 调用诺诺开票接口
* @param invoiceGuid 发票Guid
* @throws Exception
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void openInvoice(String invoiceGuid, String centerGuid) throws Exception {
TfcInvoicePO invoicePO = dao.findByPrimaryKey(invoiceGuid);
AssertU.notNull(invoicePO, "查询发票信息出错");
//1、调用开票平台开票
String redisKey = StaticValue.OPEN_INVOICE_TOKEN_PREFIX + ":" + centerGuid;
String token = getOpenToken(redisKey);
//请求头参数
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
headers.add("access_token", token);
//请求参数
Map params = buildInvoiceOrder(centerGuid, invoicePO);
HttpEntity
- 封装订单信息 buildInvoiceOrder
private Map buildInvoiceOrder(String centerGuid, TfcInvoicePO invoicePO) throws Exception {
Map params = new HashMap<>();
params.put("buyerAccount", invoicePO.getAccountBank());
params.put("buyerAddress", invoicePO.getByrAddress());
params.put("buyerName", invoicePO.getByrName());
params.put("buyerTaxNum", invoicePO.getTaxpayerNum());
params.put("buyerTel", invoicePO.getTel());
params.put("email", invoicePO.getEmail());
//p:普通发票(电票),c:普通发票(纸票),s:专用发票(纸票),b:专用发票(电票)
String invoiceType = invoicePO.getInvoiceType();
String invoiceLine = "";
if (InvoiceTypeEnum.GENERAL_ELECTRIC.getKey().equals(invoiceType)) {
invoiceLine = "p";
} else if (InvoiceTypeEnum.GENERAL_PAPER.getKey().equals(invoiceType)) {
invoiceLine = "c";
} else if (InvoiceTypeEnum.SPECIAL_ELECTRIC.getKey().equals(invoiceType)) {
invoiceLine = "b";
} else if (InvoiceTypeEnum.SPECIAL_PAPER.getKey().equals(invoiceType)) {
invoiceLine = "s";
}
params.put("invoiceLine", invoiceLine);
//蓝票
params.put("invoiceType", "1");
params.put("clerk", "xxx");
params.put("payee", "xxx");
params.put("checker", "xxx");
params.put("salerTaxNum", YBCX_TAXNUM);
// 发票明细信息
//是否有折扣(发票金额不等于合计金额,有折扣)
boolean isDiscount = !invoicePO.getInvoiceAmount().equals(invoicePO.getAmount());
//是否合并(有折扣:TRUE,不能打印明细票)
String isMerge = isDiscount ? BooleanEnum.TRUE.getKey() : (invoicePO.getDetailTicket().equals(BooleanEnum.TRUE.getKey()) ? "FALSE" : "TRUE");
//查询全部明细
List detailList = detailDAO.findDetailList(invoicePO.getGuid(), "", isMerge);
AssertU.notEmpty(detailList, "查询发票明细信息出错");
//查询商品税务税收设置信息
Map relationMap = getTaxDtoList(centerGuid, detailList);
//发票明细
ArrayList
- 开票平台B接收到C开票请求后,调用诺诺平台A开票接口,A回调B,B回调C,C更新开票单状态;
开票单状态4个,暂存,开票中,开票失败,开票完成;
开票前为暂存状态,提交开票请求后,状态会变成开票中,接收回调信息后,改变发票状态为开票失败或开票完成;
@RequestMapping("/callback")
@ResponseBody
@GreenLight
public AjaxResponse invoiceCallback(HttpServletRequest request) {
AjaxResponse response = new AjaxResponse();
//返回的内容
String content = request.getParameter("content");
Map map = JSON.parseObject(content, Map.class);
//发票流水号
String serialNo = (String) map.get("c_fpqqlsh");
//商户税号
String saleTaxNum = (String) map.get("c_saletaxnum");
try {
invoiceService.invoiceCallback(saleTaxNum, serialNo);
} catch (Exception e) {
this.packErrorResponse("服务器异常:", e);
}
return response;
}
/**
* 发票开票、红冲回调处理
* @param saleTaxNum 税号
* @param serialNo 流水号
* @throws Exception
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void invoiceCallback(String saleTaxNum, String serialNo) throws Exception {
//查询发票记录(回调接口,权限开放没有运营中心,用主运营中心获取Token)
Map data = invoiceInfoQuery(serialNo, DeptEnum.DEPT_00000000000000000000000000000001.getKey());
//发票代码
String invoiceCode = String.valueOf(data.get("invoiceCode"));
//发票号码
String invoiceNo = String.valueOf(data.get("invoiceNo"));
//状态
String status = String.valueOf(data.get("status"));
//失败原因
String failCause = String.valueOf(data.get("failCause"));
TfcInvoicePO invoicePO = dao.findBySerialNo(serialNo);
if (ObjectUtils.isEmpty(invoicePO)) {
return;
}
//更新发票状态
TfcInvoicePO updatePO = new TfcInvoicePO();
updatePO.setGuid(invoicePO.getGuid());
//开票完成("2")
if ("2".equals(status)) {
updatePO.setStatus(InvoiceStatusEnum.INVOICED.getKey());
updatePO.setInvoiced(BooleanEnum.TRUE.getKey());
updatePO.setInvoiceCode(invoiceCode);
updatePO.setInvoiceNum(invoiceNo);
} else if ("22".equals(status)) {
//开票失败("22")
updatePO.setStatus(InvoiceStatusEnum.INVOICE_FAILED.getKey());
updatePO.setFailCause(failCause);
}
dao.update(updatePO, "guid");
}