1. 程式人生 > >第三方API對接常見問題

第三方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){

}

下班了,也基本說完了,有什麼疑問可以留言,歡迎多交流,指正