背景
在 Java 开发中,调用第三方接口时,请求参数的顺序对于某些签名认证机制至关重要。百度地图开放平台的 SN 签名认证要求参数按特定顺序排列。若使用 UniHttp 框架调用此类接口,由于框架内部处理可能导致参数顺序变化,从而引发 SN 校验失败(错误码 211)。本文探讨该问题的成因及三种解决方案。
问题场景
1. UniHttp 模式下 SN 接口定义
按照官方文档规范,定义接口如下:
package com.yelang.project.thridinterface;
import com.burukeyou.uniapi.http.annotation.HttpApi;
import com.burukeyou.uniapi.http.annotation.param.QueryPar;
import com.burukeyou.uniapi.http.annotation.request.GetHttpInterface;
import com.burukeyou.uniapi.http.core.response.HttpResponse;
@HttpApi
public interface BaiduGeoSearchWithSnService {
/**
* - 百度行政区划区域检索接口
*/
@GetHttpInterface(url="https://api.map.baidu.com/place/v2/search")
public HttpResponse<String> getSearch(
@QueryPar("query") String query,
@QueryPar("region") String region,
@QueryPar("output") String output,
@QueryPar("scope") String scope,
@QueryPar("ret_coordtype") String ret_coordtype,
@QueryPar("page_size") int pageSize,
@QueryPar("page_num") int pageNum,
@QueryPar("ak") String ak,
@QueryPar("sn") String sn);
}
2. 第一次正式调用
测试类中使用 LinkedHashMap 保存参数以维持插入顺序,并计算 SN 签名:
package com.yelang.project.unihttp;
import java.io.UnsupportedEncodingException;
import java.util.LinkedHashMap;
import java.util.Map;
import org.junit.Test;
org.springframework.beans.factory.annotation.Autowired;
org.springframework.boot.test.context.SpringBootTest;
org.springframework.test.context.junit4.SpringRunner;
com.burukeyou.uniapi.http.core.response.HttpResponse;
com.yelang.project.thridinterface.BaiduGeoSearchWithSnService;
com.yelang.project.thridinterface.signature.BaiduSignature;
{
;
;
BaiduGeoSearchWithSnService bdGeoSearchWithSnService;
UnsupportedEncodingException {
Map<String, String> paramsMap = <>();
;
;
;
;
;
;
;
;
paramsMap.put(, query);
paramsMap.put(, region);
paramsMap.put(, output);
paramsMap.put(, scope);
paramsMap.put(, ret_coordtype);
paramsMap.put(, String.valueOf(pageSize));
paramsMap.put(, String.valueOf(pageNum));
paramsMap.put(, AK_VALUE);
(AK_VALUE, SK_VALUE, paramsMap, api_prefix);
signature.getSnByMap();
HttpResponse<String> result = bdGeoSearchWithSnService.getSearch(query, region, output, scope, ret_coordtype, pageSize, pageNum, AK_VALUE, sn);
System.out.println(result.getBodyResult());
}
}


