第三方API對接常見問題
JAVA專案中通常會需要通過對接第三方API來擴充套件專案業務,如支付,風控,語音識別,影象處理等。但看似簡單的傳送/接收請求卻包含了Http請求,資料加密/解密,簽名加簽/驗籤,資料處理等內容。這次通過對接某公司API,也踩了不少坑,跟大家分享一下。
1.文件/demo版本過舊,被對接方服務端程式碼已經更改,但文件未更新
一般來說,文件的易讀程度和更新速度能說明被對接公司技術部門的水平。我見過比較好的公司例如 阿里雲,連連支付,FaceId,白騎士等等。但是也有比較坑的,這一點大家就要注意了。
文件裡一般有更新時間,最近更新時間距離當前日期越近越好。
如果真的遇到比較老的文件和demo,那就多和對方技術人員溝通,搞不定的地方儘快去問對方技術,不要鑽牛角尖。
2.加密方式問題
為了防止被抓包,一般都會使用加密演算法來對請求引數進行加密,常見加密方式有,RSA,MD5,ITRUS,DES等等,如果不是有特殊要求,選擇優先順序 MD5>DES>RAS>ITRUS. 說白了就是怎麼簡單怎麼來。
注意點:
MD5加密方式有好幾種類型,一定要弄清楚要對接的介面是MD5 32位 還是 MD5 16位
JAVA開發的話 RAS加密 金鑰記得進行 PKCS8轉碼
ITRUS加密注意替換JDK中的兩個jar包:
用無限制擴充套件包替換 jdk 安裝目錄下的 local_policy.jar 和 US_export_policy.jar
例如:jdk 安裝目錄下: C:\Program Files\Java\ jdk1.8.0_31 替 換 文 件 所 在 的 目 錄 : C:\Program Files\Java\ jdk1.8.0_31 \jre\lib\security
jdk8 替換包參考:《jdk 替換包.zip》中《jce_policy-8.zip》
jdk7 替換包參考:《jdk 替換包.zip》中《UnlimitedJCEPolicyJDK7.zip》
jdk6 替換包參考:《jdk 替換包.zip》中《jce_policy-6.zip》
3.加簽驗籤問題
對引數進行加密簽名,通常都需要過濾掉空引數以及欄位signType和sign。 一般的demo中都會帶的有過濾方法,也可以自己寫,難度不大
private static Map<String, String> paraFilter(Map<String, String> oriMap) {
Map<String, String> result = new HashMap();
if (oriMap != null && oriMap.size() > 0) {
Iterator var2 = oriMap.entrySet().iterator();
while(var2.hasNext()) {
Entry<String, String> iterator = (Entry)var2.next();
String value = (String)iterator.getValue();
if (!StringUtils.isBlank(value) && !((String)iterator.getKey()).equalsIgnoreCase("sign") && !((String)iterator.getKey()).equalsIgnoreCase("sign_type")) {
result.put(iterator.getKey(), value);
}
}
return result;
} else {
return result;
}
}
加密前,注意檢查引數名是否完全和文件中相同,一個空格都不能多,也不能少。否則對方驗籤失敗,這種細節的錯誤有時候也很難找。
注意點:我喜歡用JSONObject對裝載引數,但是這裡有一個問題,fastJson工具在對jsonObject進行格式轉換處理時,可能會打亂原json物件裡的欄位順序,導致自己/對方簽名校驗敗。這裡有三個解決方案
1、解析時增加 Feature.OrderedField 引數固定順序
Map<String, String> params = JSON.parseObject(jsonStr, new TypeReference<Map<String, String>>(){}, Feature.OrderedField);
2、初始化json物件為有序物件:
JSONObject retObj = new JSONObject(true);
這樣生成的json物件就與放入資料時一致。
3、使用Gson解析
JsonObject returnData = new JsonParser().parse(replyString).getAsJsonObject();
4.HttpClient傳送請求問題
一般來說第三方API主要使用POST/GET兩種方法。按照demo或者文件中的示例能很快確定對方介面的資料格式以及請求方式,不要自己瞎猜亂寫,這樣效率太低。有的公司會直接提供SDK或者jar包供我們參考,這是極好的。
注意點:
不要輕易將sdk或者jar包引入自己專案,認真檢查是否埋有惡意程式碼。 也可以直接將需要用的程式碼複製粘貼出來,新建工具類使用。ctrl+c/ctrl+v美滋滋
傳送務必檢查是否對請求前對引數進行urlencode編碼,否則會資料被轉義,引數校驗失敗。
5.回撥問題
注意點:
1.在需要回調(非同步通知API結果)的時候,我方會使用亞瑟(霧)。。。會使用一個非同步請求介面來接受非同步通知,即使對方說明了是post或者get請求方法通知,也不要在@RequestMapping()註解中標明請求方式,這樣能給對方沒有什麼限制,不會容易發生415(bad request)錯誤碼的情況。
2.儘量不要使實力類在方法入參裡直接接引數,引數出錯了直接就是415(bad request),不容易debug,用request.getParameter()的方式寫一個工具類。遍歷處請求引數,set到物件裡,這是我們專案的類,自己寫也不難,百度你懂的
public static NoticeResp parseNotice(HttpServletRequest request) {
NoticeResp resp = new NoticeResp();
Field[] fields = NoticeResp.class.getDeclaredFields();
for (Field field : fields) {
ReflectionUtils.setFieldValue(resp, field.getName(), request.getParameter(field.getName()));
}
return resp;
}
如:
@RequestMapping("notify")
@ResponseBody
public Object notify(HttpServletRequest request, HttpServletResponse response){
}
下班了,也基本說完了,有什麼疑問可以留言,歡迎多交流,指正