前言
在實際工作中,我們經常需要在項目中調用第三方API接口,獲取數據,或者上報數據,進行數據交換和通信。
那么,調用第三方API接口會遇到哪些問題?如何解決這些問題呢?
這篇文章就跟大家一起聊聊第三方API接口的話題,希望對你會有所幫助。
1、域名訪問不到
一般我們在第一次對接第三方平臺的API接口時,可能會先通過瀏覽器或者postman調用一下,該接口是否可以訪問。
有些人可能覺得多次一舉。
其實不然。
有可能你調用第三方平臺的API接口時,他們的接口真的掛了,他們還不知道。
還有一種最重要的情況,就是你的工作網絡,是否可以訪問這個外網的接口。
有些公司為了安全考慮,對內網的開發環境,是設置了防火墻的,或者有一些其他的限制,有些ip白名單,只能訪問一些指定的外網接口。
如果你發現你訪問的域名,在開發環境訪問不通,就要到運維同學給你添加ip白名單了。
2、簽名錯誤
很多第三方API接口為了防止別人篡改數據,通常會增加數字簽名(sign)的驗證。
sign = md5(多個參數拼接 + 密鑰)
在剛開始對接第三方平臺接口時,會遇到參數錯誤,簽名錯誤等問題。
其中參數錯誤比較好解決,重點是簽名錯誤這個問題。
簽名是由一些算法生成的。
比如:將參數名和參數值用冒號拼接,如果有多個參數,則按首字母排序,然后再將多個參數一起拼接。然后加鹽(即:密鑰),再通過md5,生成一個簽名。
如果有多個參數,你是按首字母倒序的,則最后生成的簽名會出問題。
如果你開發環境的密鑰,用的生產環境的,也可能會導致生產的簽名出現問題。
如果第三方平臺要求最后3次md5生成簽名,而你只用了1次,也可能會導致生產的簽名出現問題。
因此,接口簽名在接口聯調時是比較麻煩的事情。
如果第三方平臺有提供sdk生成簽名是最好的,如果沒有,就只能根據他們文檔手寫簽名算法了。
3、簽名過期
通過上面一步,我們將簽名調通了,可以正常訪問第三方平臺獲取數據了。
但你可能會發現,同一個請求,15分鐘之后,再獲取數據,卻返回失敗了。
第三方平臺在設計接口時,在簽名中增加了時間戳校驗,同一個請求在15分鐘之內,允許返回數據。如果超過了15分鐘,則直接返回失敗。
這種設計是為了安全考慮。
防止有人利用工具進行暴力破解,不停偽造簽名,不停調用接口校驗,如果一直窮舉下去的話,總有一天可以校驗通過的。
sign = md5(多個參數拼接 + 密鑰 + 時間戳)
因此,有必要增加時間戳的校驗。
如果出現這種情況,不要慌,重新發起一次新的請求即可。
4、接口突然沒返回數據
如果你調用第三方平臺的某個API接口查詢數據,剛開始一直都有數據返回。
但突然某一天沒返回數據了。
但是該API接口能夠正常響應。
不要感到意外,有可能是第三方平臺將數據刪除了。
我對接完第三方平臺的API接口后,部署到了測試環境,發現他們接口竟然沒有返回數據,原因是他們有一天將測試環境的數據刪完了。
因此,在部署測試環境之前,要先跟對方溝通,要用哪些數據測試,不能刪除。
5、token失效
有些平臺的API接口在請求之前,先要調用另外一個API接口獲取token,然后再header中攜帶該token信息才能訪問其他的業務API接口。
在獲取token的API接口中,我們需要傳入賬號、密碼和密鑰等信息。每個接口對接方,這些信息都不一樣。
我們在請求其他的API接口之前,每次都實時調用一次獲取token的接口獲取token?還是請求一次token,將其緩存到redis中,后面直接從redis獲取數據呢?
很顯然我們更傾向于后者,因為如果每次請求其他的API接口之前,都實時調用一次獲取token的接口獲取token,這樣每次都會請求兩次接口,性能上會有一些影響。
如果將請求的token,保存到redis,又會出現另外一個問題:token失效的問題。
我們調用第三方平臺獲取token的接口獲取到的token,一般都有個有效期,比如:1天,1個月等。
在有效期內,該API接口能夠正常訪問。如果超過了token的有效期,則該API接口不允許訪問。
好辦,我們把redis的失效時間設置成跟token的有效期一樣不就OK了?
想法是不錯,但是有問題。
你咋保證,你們系統的服務器時間,跟第三方平臺的服務器時間一模一樣?
我之前遇到過某大廠,提供了獲取token接口,在30天內發起請求,每次都返回相同的token值。如果超過了30天,則返回一個新的。
有可能出現這種情況,你們系統的服務器時間要快一些,第三方平臺的時間要慢一些。結果到了30天,你們系統調用第三方平臺的獲取token接口獲取到了token還是老的token,更新到redis中了。
過一段時間,token失效了,你們系統還是用老的token訪問第三方平臺的其他API接口,一直都返回失敗。但獲取新的token卻要等30天,這個時間太漫長了。
為了解決這個問題,需要捕獲token失效的異常。如果在調用其他的API接口是發現token失效了,馬上請求一次獲取token接口,將新的token立刻更新到redis中。
這樣基本可以解決token失效問題,也能盡可能保證訪問其他接口的穩定性和性能。
6、接口超時
系統上線之后,調用第三方API接口,最容易出現的問題,應該是??接口超時?
?問題了。
系統到外部系統之間,有一條很復雜的鏈路,中間有很多環節出現問題,都可能影響API接口的相應時間。
作為API接口的調用方,面對第三方API接口超時問題,除了給他們反饋問題,優化接口性能之外,我們更有效的方式,可能是增加接口調用的失敗重試機制。
例如:
int retryCount=0;
do {
try {
doPost();
break;
} catch(Exception e) {
log.warn("接口調用失敗")
retryCount++;
}
} where (retryCount <= 3)
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
如果接口調用失敗,則程序會立刻自動重試3次。
如果重試之后成功了,則該API接口調用成功。
如果重試3次之后還是失敗,則該API接口調用失敗。
7、接口返回500
調用第三方API接口,偶爾因為參數的不同,可能會出現500的問題。
比如:有些API接口對于參數校驗不到位,少部分必填字段,沒有校驗不能為空。
剛好系統的有些請求,通過某個參數去調用該API接口時,沒有傳入那個參數,對方可能會出現NPE問題。而該接口的返回code,很可能是500。
還有一種情況,就是該API接口的內部bug,傳入不同的參數,走了不同的條件分支邏輯,在走某個分支時,接口邏輯出現異常,可能會導致接口返回500。
這種情況做接口重試也沒用,只能聯系第三方API接口提供者,反饋相關問題,讓他們排查具體原因。
他們可能會通過修復bug,或者修復數據,來解決這個問題。
8、接口返回404
如果你在系統日志中發現調用的第三方API接口返回了404,這就非常坑了。
如果第三方的API接口沒有上線,很可能是他們把接口名改了,沒有及時通知你。
這種情況,可以錘他們了。
還有一種情況是,如果第三方的API接口已經上線了,剛開始接口是能正常調用的。
第三方也沒有改過接口地址。
后來,突然有一天發現調用第三方的API接口還是出現了404問題。
這種情況很可能是他們網關出問題了,最新的配置沒有生效,或者改了網關配置導致的問題。
總之一個字:坑。
9、接口返回少數據了
之前我調過一個第三方的API接口分頁查詢數據,接入非常順利,但后來上線之后,發現他們的接口少數據了。
一查原因發現是該分頁查詢接口,返回的總頁數不對,比實際情況少了。
有些小伙伴可能會好奇,這么詭異的問題我是怎么發現?
之前調用第三方API接口分頁查詢分類數據,保存到我們的第三方分類表中。
突然有一天,產品反饋說,第三方有個分類在分類樹中找不到。
我確認之后,發現竟然是真的沒有。
從調用第三方API接口的響應日志中,也沒有查到該分類的數據。
這個API接口是分頁查詢接口,目前已經分了十幾頁查詢數據,但還是沒有查到我們想要的分類。
之前的做法是先調用一次API接口查詢第一頁的數據,同時查出總頁數。然后再根據總頁數循環調用,查詢其他頁的數據。
我當時猜測,可能是他們接口返回的總頁數有問題。
于是,可以將接口調用邏輯改成這樣的:
- 從第一頁開始,后面每調用一次API接口查數據,頁數就加1。然后判斷接口返回的數據是否小于pageSize,
- 如果不小于,則進行下一次調用。
- 如果小于,則說明已經是最后一頁了,可以停止后續調用了。
驗證之后發現這樣果然可以獲取那個分類的數據,只能說明第三方的分頁查詢接口返回的總頁數比實際情況小了。
10、偷偷改參數了
我之前調用過某平臺的API接口獲取指標的狀態,之前根據雙方約定的狀態有:正常和禁用 兩種。
然后將狀態更新到我們的指標表中。
后來,雙方系統上線運行了好幾個月。
突然有一天,用戶反饋說某一條數據明明刪除了,為什么在頁面上還是可以查到。
此時,我查我們這邊的指標表,發現狀態是正常的。
然后查看調用該平臺的API接口日志,發現返回的該指標的狀態是:下架。
what?
這是什么狀態?
跟該平臺的開發人員溝通后,發現他們改了狀態的枚舉,增加了:上架、下架等多個值,而且沒有通知我們。
這就坑了。
我們這邊的代碼中判斷,如果狀態非禁用狀態,都認為是正常狀態。
而下架狀態,自動被判斷為正常狀態。
經過跟對方溝通后,他們確認下架狀態,是非正常狀態,不應該顯示指標。他們改了數據,臨時解決了該指標的問題。
后來,他們按接口文檔又改回了之前的狀態枚舉值。
11、接口時好時壞
不知道你在調用第三方接口時,有沒有遇到過接口時好時壞的情況。
5分鐘前,該接口還能正常返回數據。
5分鐘后,該接口返回503不可用。
又過了幾分鐘,該接口又能正常返回數據了。
這種情況大概率是第三方平臺在重啟服務,在重啟的過程中,可能會出現服務暫時不可用的情況。
還有另外一種情況:第三方接口部署了多個服務節點,有一部分服務節點掛了。也會導致請求第三方接口時,返回值時好時壞的情況。
此外還有一種情況:網關的配置沒有及時更新,沒有把已經下線的服務剔除掉。
這樣用戶請求經過網關時,網關轉發到了已經下線的服務,導致服務不可用。網關轉發請求到正常的服務,該服務能夠正常返回。
如果遇到該問題,要盡快將問題反饋給第三方平臺,然后增加接口失敗重試機制。
12、文檔和接口邏輯不一致
之前還遇到一個第三方平臺提供的API查詢接口,接口文檔中明確寫明了有個??dr?
?字段表示??刪除狀態?
?。
有了這個字段,我們在同步第三方平臺的分類數據時,就能夠知道有哪些數據是被刪除的,后面可以及時調整我們這邊的數據,將相關的數據也做刪除處理。
后來發現有些分類,他們那邊已經刪除了,但是我們這邊卻沒刪除。
這是啥情況呢?
代碼邏輯很簡單,我review了一下代碼,也沒有bug,為什么會出現這種情況呢?
追查日志之后發現,調用第三方平臺獲取分類接口時,對方并沒有把已刪除的分類數據返回給我們。
也就是說接口文檔中的那個dr字段沒有什么用,接口文檔和接口邏輯不一致。
這個問題估計好多小伙伴都遇到過。
如果要解決這個問題,主要的方案有兩種:
- 第三方平臺按文檔修改接口邏輯,返回刪除狀態。
- 我們系統在調用分類查詢接口之后,根據分類code判斷,如果數據庫中有些分類的code不在接口返回值中,則刪除這些分類。
13、欠費了
我們調用過百度的票據識別接口,可以自動識別發票信息,獲取發票編號和金額等信息。
之前是另外一個同事對接的接口,后來他離職了。
發票識別功能上線,使用了很長一段時間,一直都沒有出問題。
后來,某一天,生產環境用戶反饋發票識別不了了。
我查詢了相關服務的日志,沒有發現異常,這就奇怪了。
打開代碼仔細看了一下,發現那位同事的代碼中調用第三方的API接口,接收響應數據時,直接轉換成了對象,沒有打印當時返回的字符串。
莫非,接口返回值有問題?
后來,我增加了日志,打印出了該接口真正的返回內容值。
原因一下查到了,原來是欠費了。
如果出現該了異常,百度的API接口返回的數據結構,用之前那位同事的實體有些參數沒法獲取到。
這是一個不小的坑。
我們在接收第三方API接口返回數據時,盡可能先用字符串接收返回值,然后將字符串轉換成相應實體類,一定要將該返回值在日志中打印出來,方便后面定位問題。
不要直接用實體對象接收返回值,有些API接口,如果出現不同的異常,返回的數據結構差異比較大。
有些異常結果可能是他們網關系統直接返回的,有些異常是他們業務系統返回的。
其實,我們之前還遇到過其他坑,比如:調用分類樹查詢接口,但第三方返回的數據有重復的id,我們這邊該如何處理這種異常數據呢?
我們在job中循環調用第三方API接口獲取數據,如果其中某一次調用失敗了,是try/catch捕獲異常呢?繼續執行后面的調用,還是直接終止當前的程序?如果try/catch如何保證數據一致性?終止當前程序,該如何處理后續的流程?