:question:如何對請求順豐API


分析結果:
用戶注冊成為 CP得到 partnerID ,傳 serviceCode 來指定的調用的 API服務代碼,按指定的加密方式得到 數字簽名 ,再把 相關請求的報文、時間戳、UUID隨機數 作為參數,請求結果。
:newspaper:請求報文分析
每個請求的報文有所不同
這里以 路由查詢報文 來分析
報文元素

報文示例
{
"language": "0",
"trackingType": "1",
"trackingNumber": ["444003077898", "441003077850"],
"methodType": "1"
}
復制代碼
按照相關格式填寫業務中的需要查詢的快遞訂單id進去,實現相關查詢
:chestnut:Demo實踐
Demo 代碼

目標1:PostMan發送路由查詢請求
目標:使用 POSTMAN發送一個路由查詢請求
??填參準備
?注意設置請求頭


??最重要的數字簽名
文檔中有加密demo
修改后輸出需要的參數
public static void main(String[] args) throws UnsupportedEncodingException, NoSuchAlgorithmException {
// 請求唯一號
String requestID = UUID.randomUUID().toString().replace("-", "");
//時間戳 取報文中的timestamp(調用接口時間戳)
String timestamp = String.valueOf(System.currentTimeMillis());
//客戶校驗碼 使用順豐分配的客戶校驗碼
String checkword = "XXXXXXX";
//業務報文 去報文中的msgData(業務數據報文)
String msgData = "{n"language": "0", "trackingType": "1", "trackingNumber": ["444003077898", "441003077850"], "methodType": "1" }";
//將業務報文+時間戳+校驗碼組合成需加密的字符串(注意順序)
String toVerifyText = msgData+timestamp+checkWord;
//因業務報文中可能包含加號、空格等特殊字符,需要urlEnCode處理
toVerifyText = URLEncoder.encode(toVerifyText,"UTF-8");
//進行Md5加密
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(toVerifyText.getBytes("UTF-8"));
byte[] md = md5.digest();
//通過BASE64生成數字簽名
String msgDigest = new String(new BASE64Encoder().encode(md));
System.out.println("時間戳:"+timestamp);
System.out.println("請求唯一號:"+requestID);
System.out.println("加密后的數字簽名:"+msgDigest);
}
復制代碼
運行得到相關參數:

再填入剩下的參數

請求成功
目標2:JAVA請求路由查詢 API
目標:用 Java實現 post請求路由查詢
就是從使用PostMan發送請求到在 Java中使用 HTTP請求工具類,對服務器傳參,發送請求
添加HTTP請求工具類請求接口
import org.Apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public class HttpClientUtil {
private static Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);
public static String postSFAPI(String url, String xml, String verifyCode) {
CloseableHttpClient httpClient = HttpClients.createDefault();
List<NameValuePair> parameters = new ArrayList<>();
parameters.add(new BasicNameValuePair("xml", xml));
parameters.add(new BasicNameValuePair("verifyCode", verifyCode));
HttpPost post = postForm(url, new UrlEncodedFormEntity(parameters, StandardCharsets.UTF_8));
String body = "";
body = invoke(httpClient, post);
try {
httpClient.close();
} catch (IOException var9) {
logger.error("HttpClientService post error", var9);
}
return body;
}
private static String invoke(CloseableHttpClient httpclient, HttpUriRequest httpost) {
HttpResponse response = sendRequest(httpclient, httpost);
String body = "";
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) {
body = parseResponse(response);
}
return body;
}
private static String parseResponse(HttpResponse response) {
HttpEntity entity = response.getEntity();
String body = "";
try {
if (entity != null) {
body = EntityUtils.toString(entity);
}
} catch (ParseException | IOException var4) {
logger.error("HttpClientService paseResponse error", var4);
}
return body;
}
private static HttpResponse sendRequest(CloseableHttpClient httpclient, HttpUriRequest httpost) {
CloseableHttpResponse response = null;
try {
response = httpclient.execute(httpost);
} catch (IOException var4) {
logger.error("HttpClientService sendRequest error", var4);
}
return response;
}
private static HttpPost postForm(String url, StringEntity entity) {
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(entity);
return httpPost;
}
public static String post(String url, Map<String, String> params) throws UnsupportedEncodingException {
CloseableHttpClient httpClient = HttpClients.createDefault();
RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(5000).setConnectTimeout(5000).setSocketTimeout(60000).build();
HttpPost httpPost = new HttpPost(url);
httpPost.setConfig(requestConfig);
httpPost.addHeader("Content-Type", "Application/x-www-form-urlencoded;charset=UTF-8");
List<NameValuePair> paramsList = new ArrayList<>();
Iterator<Map.Entry<String, String>> iterator = params.entrySet().iterator();
for (Map.Entry<String, String> entry : params.entrySet()) {
paramsList.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(paramsList, "UTF-8");
httpPost.setEntity(urlEncodedFormEntity);
String body = invoke(httpClient, httpPost);
try {
httpClient.close();
} catch (IOException var9) {
logger.error("HttpClientService post error", var9);
}
return body;
}
}
復制代碼
調用工具類請求API 添加代碼
Map<String,String> params = new HashMap<>();
params.put("requestID",requestID);
params.put("msgDigest",msgDigest);
params.put("msgData",msgData);
params.put("timestamp",timestamp);
params.put("partnerID","xxxxxx");
params.put("serviceCode","EXP_RECE_SEARCH_ROUTES");
String result = null;
try {
result = HttpClientUtil.post("https://sfapi-sbox.sf-express.com/std/service", params);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
System.out.println(result);
復制代碼
請求成功

目標3:舉一反三
猜想:
只改變請求的服務代碼和請求的報表亦可成功訪問對應的服務?
前提條件
接入其他 API時,需要先申請權限

修改請求參數
- serviceCode服務代碼
- msgData請求報表
建議抽取靜態變量,方便修改
下面試著請求 下訂單 接口
// 現在指定 API的服務名
private static String SERVICE_CODE = "EXP_RECE_CREATE_ORDER";
// 請求報文
private static String msgData = "{
"cargoDetails":[
{
"count":2.365,
"unit":"個",
"weight":6.1,
"amount":100.5111,
"currency":"HKD",
"name":"護膚品1",
"sourceArea":"CHN"
}],
"contactInfoList": [
{
"address":"廣東省深圳市南山區軟件產業基地11棟",
"contact":"小曾",
"contactType":1,
"country":"CN",
"postCode":"580058",
"tel":"4006789888"
},
{
"address":"廣東省廣州市白云區湖北大廈",
"company":"順豐速運",
"contact":"小邱",
"contactType":2,
"country":"CN",
"postCode":"580058",
"tel":"18688806057"
}],
"language":"zh_CN",
"orderId":"OrderNum20200612223"
}";
復制代碼
直接運行

測試成功
:statue_of_liberty:總結
我們嘗試了 使用 postman對路由查詢 API發出請求,
Java使用 HTTP工具類來接入路由查詢 API,
同時舉一反三地接入了生成訂單 API
當然 Demo還可以進一步進行完善
Demo 完善展望
- 封裝報文
- 抽取服務代碼做枚舉類
- 聲明用戶屬性的常量