公司兩個系統。 我們的A系統要給B系統上送業務簽約單申請。B系統接收數據後,非同步處理,簽約完成會主動發送通知給我們的A系統。 介面文檔里說明瞭,通過http協議的post請求來發送非同步通知,報文是json格式字元串。But,But,But, ...
公司兩個系統。
我們的A系統要給B系統上送業務簽約單申請。B系統接收數據後,非同步處理,簽約完成會主動發送通知給我們的A系統。
介面文檔里說明瞭,通過http協議的post請求來發送非同步通知,報文是json格式字元串。
我們A系統定義restful的http介面。
【題外話】@RequestBody註解:@RequestBody接收的參數是來自requestBody中,即請求體。適用於http post請求。請求端通過HttpEntity傳遞參數,併在請求頭中聲明數據的類型Content-Type,SpringMVC通過使用 HandlerAdapter 配置的HttpMessageConverters來解析HttpEntity中的數據,然後綁定到相應的bean上。
@RestController @Slf4j public class TaxNotifyController { @Reference private TaxNotifyService taxNotifyService; /** * * @param notifyVO * @return */ @PostMapping("/ayncNotify") @UnAuthToken public String ayncNotify(@RequestBody NotifyVO notifyVO){ log.info("收到回調----非同步回調----非同步通知----回調通知:{}", JSON.toJSONString(notifyVO)); String respText = taxNotifyService.ayncNotify(notifyVO); log.info("回調----非同步回調----非同步通知----回調通知 回寫內容:{}",respText); return respText; } }
QA在測試過程中,發現我方一直收不到對方的回調。有對方日誌截圖為證。
查看我們A系統的log。並沒有發現“收到回調----非同步回調----非同步通知----回調通知”這樣的log。
難道是B系統到我們A系統的網路不通?雙方都是測試環境呀!還是去找運維確認吧。
[root@localhost logs]# curl http://192.168.40.84:8802/ent-boot/ayncNotify {"code":"ERROR","message":"Request method 'GET' not supported"}
因為需要POST,所以curl接收到這個錯誤。但至少證明這2個系統間的網路是沒問題的。
再次確認我方log。發現蛛絲馬跡:
2019-12-13 11:07:01.894 [http-nio-8802-exec-9] INFO com.emaxcard.car.filter.CrosXssFilter:40 -
CrosXssFilter.......orignal url:/ent-boot/ayncNotify,ParameterMap:{} 2019-12-13 11:07:01.895 [http-nio-8802-exec-9] WARN o.s.w.s.m.support.DefaultHandlerExceptionResolver:197 -
Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'text/xml;charset=UTF-8' not supported] 2019-12-13 11:07:01.895 [http-nio-8802-exec-9] INFO com.emaxcard.car.filter.CrosXssFilter:44 -
CrosXssFilter..........doFilter url:/ent-boot/ayncNotify,ParameterMap:{}
莫非,對方給的content-type是text/xml??
找B系統的開發同學,經查代碼里HttpUtil,果然,指定的content-type是text/xml。 如下圖。我們知道,springmvc預設接收數據的格式是json方式序列化的。你指定成xml格式,顯然springmvc在反序列化成NotifyVO對象時會拋出異常。自然,就不會執行這個action方法了,所以,我們沒看到那條“收到回調----非同步回調----非同步通知----回調通知”log。
【題外話】關於springmvc的messageconverter設置,可以查看spirng-web.jar里的RestTemplate.java源碼。
Line122:jsonbPresent = ClassUtils.isPresent("javax.json.bind.Jsonb", classLoader);
接著說,我們讓這位開發同學改成 application/json 後,問題得以解決。
But,But,But,下午,QA在測試付款單的回調的時候,同樣的問題又出現了,我們接收不到請求報文。一看log,又是text/xml搞的鬼。B系統的這個付款回調是另一個同學開發的。考慮到目前已經有外部商戶接入B系統,他們不准備改了。
不改就不改吧,B系統他們不改,只好我們A系統改了。話說回來,即便他們現在不改,日後有其他商戶對接聯調時,也難免會出現類似的問題。那,就是以後的事兒了。
我們怎麼改呢?那就不直接從RequestBody里接收NotfiyVO對象了,改成接收String字元串。然後,在方法里來做判斷和反序列化。改後的代碼為:
@PostMapping("/ayncNotify") @UnAuthToken public String ayncNotify(@RequestBody String notifyStr){ log.info("收到回調----非同步回調----非同步通知----回調通知:{}", notifyStr); if(StringUtils.isBlank(notifyStr)){ log.info("回調通知為空"); return "ERROR-回調通知請求參數為空"; } NotifyVO notifyVO = JSON.parseObject(notifyStr,NotifyVO.class); log.info("回調轉換NotifyVo:{}",notifyVO); String respText = taxNotifyService.ayncNotify(notifyVO); log.info("回調----非同步回調----非同步通知----回調通知 回寫內容:{}",respText); return respText; }
THE END.
下午得知,一同學在對接付款介面時,當付款介面返回受理失敗時,他把付款單的付款結果改成了失敗。這可要不得呀!付款結果一定要通過付款查詢介面來查。查詢返回付款成功,則付款成功;查詢返回付款失敗,則付款失敗;對於查詢到的其他結果,保守起見,都視為付款中即可,然後由人工來干預。技術人員千萬別自作主張,把某些不明確的結果定為付款失敗。萬一齣現重覆付款,那就尷尬了。我在2016年那時剛開始做聚合支付時,是有這樣的慘痛經歷的。
☞ Stay Hungry,Stay Foolish.