系統對接API調用


在與公司外部系統對接時,API接口一般采用REST風格,對外暴露HTTP服務。只需要將入參封裝好,並發起HTTP請求即可。具體請求流程如下圖所示:

數據格式

 API調用參數分為系統參數和業務參數,請求時,系統參數是必傳的,否則無法成功請求,業務參數由具體業務接口定義。

系統參數
名稱 類型 必填 描述
apiKey String 分配給供應商的唯一身份標識
sign String 請求簽名,生成規則參見簽名機制
timestamp String 時間戳,參見時間戳 


API請求返回結果目前支持json和xml格式,具體返回格式由請求頭中的Content-Type屬性來決定。當Content-Type屬性為application/xml時,返回xml格式,其余情況下統一返回json格式。返回結果包含以下字段

系統參數
名稱 類型 必填 描述
returnCode int 結果碼,具體值參見API返回碼
errorMsg String 異常時錯誤信息
data String 返回結果
success boolean 是否請求成功

 

請求示例

我們以團期信息管理接口為例,假設我們需要維護團期,接口請求原始入參(業務參數+系統參數)如下.

{
    "apiKey": "testApiKey",//系統參數
    "timestamp": "2015-07-30 12:34:56",//系統參數
    "agencyProductId": "test10001",//業務參數
    "groupNum": "",//業務參數
    "planInfo": [//業務參數
        {
            "planDateStr": "2015-07-18",
            "datePriceList": [
                {
                    "schemeId": "scheme0001",
                    "scheduleId": "schedule",
                    "agencyBudget": 1000,
                    "agencyBudgetChild": 500,
                    "excludeChild": 1,
                    "roomAddBudget": 100,
                    "roomGapFlag": 1,
                    "aheaddate": 4,
                    "deadlinedate": 3,
                    "deadlinehour": 18,
                    "promoFlag": 1,
                    "setGroupFlag": 1,
                    "stuffEndDate": 5
                }
            ]
        }
    ]
}

首先,我們需要根據現有參數生成簽名,簽名生成步驟如下:

1. 將入參按照一級key值進行排序(按字典順序進行排序,忽略大小寫),去掉value值為空的入參,我們將得到以下格式參數(業務參數+系統參數)如下

{
    "agencyProductId": "test10001",
    "apiKey": "testApiKey",
    "planInfo": [
        {
            "planDateStr": "2015-07-18",
            "datePriceList": [
                {
                    "schemeId": "scheme0001",
                    "scheduleId": "schedule",
                    "agencyBudget": 1000,
                    "agencyBudgetChild": 500,
                    "excludeChild": 1,
                    "roomAddBudget": 100,
                    "roomGapFlag": 1,
                    "aheaddate": 4,
                    "deadlinedate": 3,
                    "deadlinehour": 18,
                    "promoFlag": 1,
                    "setGroupFlag": 1,
                    "stuffEndDate": 5
                }
            ]
        }
    ],
    "timestamp": "2015-07-30 12:34:56"
}

2. 獲取一級key和對應的value,例如上面參數中planInfo鍵,對應的值為[{"planDateStr":"2015-07-18","datePriceList":[{"schemeId":"scheme0001","scheduleId":"schedule","agencyBudget":1000,"agencyBudgetChild":500,"excludeChild":1,"roomAddBudget":100,"roomGapFlag":1,"aheaddate":4,"deadlinedate":3,"deadlinehour":18,"promoFlag":1,"setGroupFlag":1,"stuffEndDate":5}]}], 以字符串的形式把key+value拼接起來得到一個新的字符串(二級三級鍵不進行操作),如下:

planInfo[{"planDateStr":"2015-07-18","datePriceList":[{"schemeId":"scheme0001","scheduleId":"schedule","agencyBudget":1000,
"agencyBudgetChild":500,"excludeChild":1,"roomAddBudget":100,"roomGapFlag":1,"aheaddate":4,"deadlinedate":3,"deadlinehour":18,
"promoFlag":1,"setGroupFlag":1,"stuffEndDate":5}]}]

其他鍵值對同樣如此,將拼裝好的字符串再依次拼接起來,如下:

agencyProductIdtest10001apiKeytestApiKeyplanInfo[{"planDateStr":"2015-07-18","datePriceList":[{"schemeId":"scheme0001","scheduleId":"schedule",
"agencyBudget":1000,"agencyBudgetChild":500,"excludeChild":1,"roomAddBudget":100,"roomGapFlag":1,"aheaddate":4,"deadlinedate":3,"deadlinehour":18,
"promoFlag":1,"setGroupFlag":1,"stuffEndDate":5}]}]timestamp2015-07-30 12:34:56

3. 在拼好的字符串前后都加上簽名密鑰,我們假設密鑰是ZbWjUMYevqT9Tnup4jRs,可以得到以下字符串:

ZbWjUMYevqT9Tnup4jRsagencyProductIdtest10001apiKeytestApiKeyplanInfo[{"planDateStr":"2015-07-18","datePriceList":[{"schemeId":"scheme0001",
"scheduleId":"schedule","agencyBudget":1000,"agencyBudgetChild":500,"excludeChild":1,"roomAddBudget":100,"roomGapFlag":1,"aheaddate":4,
"deadlinedate":3,"deadlinehour":18,"promoFlag":1,"setGroupFlag":1,"stuffEndDate":5}]}]timestamp2015-07-30 12:34:56ZbWjUMYevqT9Tnup4jRs

4. 對生成的字符串進行MD5加密,並將結果全部轉為大寫,獲得簽名值:

85F60EFE28BB4688F3BA4A37FF62C101

5. 將簽名加入到入參中:

{
    "agencyProductId": "test10001",
    "apiKey": "testApiKey",
    "planInfo": [
        {
            "planDateStr": "2015-07-18",
            "datePriceList": [
                {
                    "schemeId": "scheme0001",
                    "scheduleId": "schedule",
                    "agencyBudget": 1000,
                    "agencyBudgetChild": 500,
                    "excludeChild": 1,
                    "roomAddBudget": 100,
                    "roomGapFlag": 1,
                    "aheaddate": 4,
                    "deadlinedate": 3,
                    "deadlinehour": 18,
                    "promoFlag": 1,
                    "setGroupFlag": 1,
                    "stuffEndDate": 5
                }
            ]
        }
    ],
    "timestamp": "2015-07-30 12:34:56",
    "sign": "85F60EFE28BB4688F3BA4A37FF62C101"
}

6.發起HTTP請求。

附上MD5加密方法參考示例:

private static String Md5Encode(String str) throws NoSuchAlgorithmException { StringBuilder sign = new StringBuilder(); MessageDigest md = MessageDigest.getInstance("MD5"); byte[] bytes = md.digest(str.getBytes()); for (int i = 0; i < bytes.length; i++) { String hex = Integer.toHexString(bytes[i] & 0xFF); if (hex.length() == 1) { sign.append("0"); } sign.append(hex.toUpperCase()); } return sign.toString(); }

在spring-core包中提供了一個MD5加密工具!

org.springframework.util.DigestUtils#md5DigestAsHex(byte[])

注意事項

1. 所有的請求和響應數據編碼皆為utf-8格式

2. 生成簽名時,空值的參數不參與校驗

3. 生成簽名時,參數名稱和值大小寫敏感

4. 排序規則為按字典順序進行排序,忽略大小寫

附代碼實現:

public class APITest { public static void main(String[] args) throws NoSuchAlgorithmException { String s = "{\n" +
                "    \"apiKey\": \"testApiKey\",\n" +
                "    \"timestamp\": \"2015-07-30 12:34:56\",\n" +
                "    \"agencyProductId\": \"test10001\",\n" +
                "    \"groupNum\": \"\",\n" +
                "    \"planInfo\": [\n" +
                "        {\n" +
                "            \"planDateStr\": \"2015-07-18\",\n" +
                "            \"datePriceList\": [\n" +
                "                {\n" +
                "                    \"schemeId\": \"scheme0001\",\n" +
                "                    \"scheduleId\": \"schedule\",\n" +
                "                    \"agencyBudget\": 1000,\n" +
                "                    \"agencyBudgetChild\": 500,\n" +
                "                    \"excludeChild\": 1,\n" +
                "                    \"roomAddBudget\": 100,\n" +
                "                    \"roomGapFlag\": 1,\n" +
                "                    \"aheaddate\": 4,\n" +
                "                    \"deadlinedate\": 3,\n" +
                "                    \"deadlinehour\": 18,\n" +
                "                    \"promoFlag\": 1,\n" +
                "                    \"setGroupFlag\": 1,\n" +
                "                    \"stuffEndDate\": 5\n" +
                "                }\n" +
                "            ]\n" +
                "        }\n" +
                "    ]\n" +
                "}"; String signature = getSignature(s, "ZbWjUMYevqT9Tnup4jRs"); System.out.println(Md5Encode(signature)); } public static String getSignature(String requestData, String secretKey) { //第一步,獲取所有值非空的key
        List<String> keyList = new ArrayList<String>();  Map<String,Object> data = JsonUtil.toBean(requestData,Map.class); for (String key : data.keySet()) { if (key == null) { continue; } //value為null或空
            if (data.get(key) == null || StringUtils.isBlank(data.get(key).toString())) { continue; } keyList.add(key); } //按名稱排序並拼接成字符串
        String[] arrayToSort = keyList.toArray(new String[keyList.size()]); Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER); StringBuilder sb = new StringBuilder(secretKey); for (String key : arrayToSort) { sb.append(key); sb.append(JsonUtil.toString(data.get(key))); } sb.append(secretKey); System.out.println(sb.toString()); return sb.toString(); } /** * MD5 加密 * @param str 需要加密的字符串 * @return 經過加密的字符串 * @throws NoSuchAlgorithmException */
    private static String Md5Encode(String str) throws NoSuchAlgorithmException { StringBuilder sign = new StringBuilder(); MessageDigest md = MessageDigest.getInstance("MD5"); byte[] bytes = md.digest(str.getBytes()); for (int i = 0; i < bytes.length; i++) { String hex = Integer.toHexString(bytes[i] & 0xFF); if (hex.length() == 1) { sign.append("0"); } sign.append(hex.toUpperCase()); } return sign.toString(); } }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM