一 故事背景
杨乐乐接到一个新需求,针对单据进行删改单的审核,乐乐完成需求后,由于系统存在其他的问题,导致他的功能无法在测试环境测试,由此开始了苦闷的问题排查之旅
二 项目问题
单据在船代系统进行确认后,因为单据是预存扣款单据,所以单据的状态要先被置为确认中,等结算系统中单据对应的商品被支付了并且将支付状态回填给船代,船代单据的确认状态会被置为已确认,但是,现在的问题是,单据的状态一直在确认中。
三 业务流程分析
sequenceDiagram
船代系统->>结算系统: 生成商品
结算系统-->>支付系统: 支付商品
支付系统-)结算系统: 商品已支付
结算系统-)船代系统: 更新费用状态及单据确认状态
上面为业务流程,但是问题来了,到底是哪一点出了问题。这里涉及到业务问题,也涉及到对系统中代码的了解,如商品有没有生成,在哪个表生成?
四 排查
预存扣款,船代发请求给结算
1)通过功能查询:
- 在商品->商品管理,商品关键字根据提单号可以查询出生成的商品
- 查看商品有没有扣款 查看客户订单管理与查询
2)通过代码查询 @RequestMapping( path = "/xxxxxx", method = {RequestMethod.GET, RequestMethod.POST}) @ResponseBody @ResponseStatus(HttpStatus.OK) public String createProduct(@RequestParam("system_flag") String systemFlag, @RequestParam(value = "call_back_url", required = false, defaultValue = "") String callBackUrl, @RequestParam("product_json") String productJson) { DataSet dataSet = new DataSet(); try { logger.info("calling /xxxxxx start: systemFlag : [{}], callBackUrl:[{}], productJson:[{}]", 对应数据库表 select * from pdt_product WHERE NAME ='7788877' 查询出该单已生产商品,及调用的支付回填处理类
支付回填
通过kibana查看日志 关键词 productJson 在支付回填处理类中看到插入了CD_PAY_NOTICE_MSG表 通过日志查询赋值是在intf项目PayingNotifyListener类的notifyInternal方法 private void notifyInternal(PayTrade trade, PayingNotifyEvent event) throws Exception {
这个方法更新了CD_PAY_NOTICE_MSG表内容为船代回填通知发送成功,并且调用了船代接口
public String updateFreightStatus(UpdateFreight updateFreight) throws IOException { logger.debug("test_freight:" + updateFreight); String json = Serializing.json().toString(updateFreight); Map<String, String> params = Maps.newHashMap(); params.put("updateFreight", json); HttpResult result = this.execute(this.httpPost(params), new String[]{"sa/xxxxx"}); logger.debug("test_freight_result:" + result.content); return result.content; }
船代逻辑处理
在船代查找调用接口,最终找到是在下面方法进行了舱单确认状态修改
/** * 更新费用状态 * * @param event .businessId 费用ID * @param event .status 费用状态步骤: 结束查询费用 * @return */ public String updateFreightStatus(SettleMentEvent event) throws Exception { // 如果走这个逻辑 就会造成舱单一直确认中 if (flag) { // 船代未收费用金额为0,发起退款 0:人工审批 1:自动审批 this.bus.asyncPost(new RefundProductEvent(event.getProductId(), 1)); event.printTime("发起退款,结束"); return "yes"; } // 在这里修改确认状态 for (RpFreight rpFreight : rpFreights) { JsToBusinessFreightEvent businessEvent = new JsToBusinessFreightEvent(Integer.toString(rpFreight.getBusinessType()), 1, rpFreight.getGatheringBy(), rpFreight.getGatheringTime(), rpFreight.getPaymentNo(), rpFreight.getPaymentType(), rpFreight.getPayMail(), rpFreight.getPayName(), rpFreight.getPayCompany(), rpFreight.getPayPhone(), rpFreight.getBusinessFreightId(), event.getPayMethod()); logger.info("开始更新业务费用: {}", Serializing.json().toString(businessEvent)); this.bus.asyncPost(businessEvent); }
如果在船代查询不到费用,费用的状态就会一直确认中,这次的确认中是因为没有查询到费用
电子钱包月不足情况也会造成确认中
根据通知表也可查电子钱包月不足情况
select * from CD_PAY_NOTICE_MSG where product_id ='8a8ac83c795e85f8017964447cdc0c75'
五 结语
很多时候问题的排查依赖的更多的是业务能力,以及对系统的了解还有对系统中代码的了解,你知道一段代码的处理写在哪,你知道这个功能该查哪个数据库表,你知道整个系统的交互流程,这些都是与技术无关的,但是在实际开发中,却是程序员必须知道知识,这样才能更高效的解决问题。