of an open platform developed by imitating JD.COM platform framework includes requirements server codes and SDK codes
- 2021-09-20 20:34:37
- OfStack
1 Open Platform Requirements
Users need to assemble a correct URL according to the protocol specification of the open platform, and request to the open platform through Https to obtain the required data. The main process includes: filling in parameters, generating signatures, assembling HTTPS requests, initiating requests, obtaining response results, and parsing results.
1.1 Call parameters
参数名称 |
参数类型 |
是否必传 |
参数描述 |
method |
String |
是 |
API接口名称 |
access_token |
String |
是 |
采用OAuth授权方式是必填参数 |
app_key |
String |
是 |
应用的app_key |
sign |
String |
是 |
详见下文“5.签名算法”描述 |
timestamp |
String |
是 |
时间戳,格式为yyyy-MM-dd HH:mm:ss,例如:2019-05-01 00:00:00。API服务端允许客户端请求时间误差为10分钟 |
format |
String |
否 |
暂时只支持json |
v |
String |
是 |
API协议版本,参考接口文档版本 |
360buy_param_json |
String |
是 |
需要将应用级参数作为1个整体对象以json的形式拼接传递 |
Application-level parameters (refer to interface documentation for more API application parameters)
1.2 Signature algorithm
In order to prevent API from being intercepted and tampered by malicious people during the calling process, it is necessary to pass in signature parameters when calling API, and the open platform server will verify the signature according to the request parameters to judge whether the request parameters are legal or not. The process of open platform signature rules is as follows:
Arrange all request parameters in alphabetical order, such as access_token, app_key, method, timestamp, v, 360buy_param_json,
The order is 360buy_param_json, access_token, app_key, method, timestamp, v
Splice all parameter names and values, for example: 360buy_param_jsonxxxaccess_tokenxxxapp_keyxxxmethodxxxxxxtimestampxxxxxxvx
Clamp appSecret at both ends of a string (spliced string in the previous step), for example: appSecret+XXXX+appSecret
Encrypt with MD5 and convert to uppercase.
2 server code, Java example
The server is written based on SpringBoot framework, the entry is placed in Controller, and the business logic is written in Service. Considering security and convenience of troubleshooting, input checksum access log will be added.
2.1 Interface entry code
The interface has only one entry, that is, the Controller code is as follows:
@Controller
public class RouterController {
@Resource
private RouterService routerService;
@Resource
private OpenApiLogService openApiLogService;
/**
* API Interface router, interface entry
*
* @param request
* @param zrsc_param_json
* @return
*/
@RequestMapping(value = "routerjson", method = RequestMethod.POST)
@ResponseBody
public String routerjson(HttpServletRequest request, String zrsc_param_json) {
if (zrsc_param_json==null||"".equals(zrsc_param_json)) {
return JsonUtils.objToJson(APIMessageVo.fail(APIErrorEnum.FAIL_PARA_LOSE.getCode(), APIErrorEnum
.FAIL_PARA_LOSE.getName()));
}
APIMessageVo aPIMessageVo=openApiLogService.secrityCheck(request);
if(aPIMessageVo.isSuccess()){// Safety inspection is successful
aPIMessageVo=routerService.router(request, zrsc_param_json);
openApiLogService.insert(request,aPIMessageVo);
}
return JsonUtils.objToJson(aPIMessageVo);
}
}
2.2 Business Logic Layer
Business logic layer, simple examples, different businesses are different.
public APIMessageVo router(HttpServletRequest request, String zrsc_param_json) {
String access_token = request.getParameter("access_token");
String app_key = request.getParameter("app_key");
String method = request.getParameter("method");
String sign = request.getParameter("sign");
APIMessageVo checkResult=this.routerParaCheck(request, zrsc_param_json,access_token,app_key,method,sign);
if(!checkResult.isSuccess()){// Entry detection failed
return checkResult;
}
if (APPInterfaceNameEnum.API_ADDRESS_ADDRESS2PROVICECITY_GET.getName().equals(method)) {// Get provincial and municipal streets
return this.address2provincecity(zrsc_param_json);
} else {// Interface does not exist
return APIMessageVo.fail(APIErrorEnum.FAIL_NOT_FOUND_INTERFACE.getCode(), APIErrorEnum.FAIL_NOT_FOUND_INTERFACE.getName());
}
}
private APIMessageVo routerParaCheck(HttpServletRequest request, String zrsc_param_json, String access_token,
String app_key, String method, String sign){
//*************** Parameter check ***************
if (StringUtils.isBlank(access_token) || StringUtils.isBlank(app_key) || StringUtils.isBlank(method) ||
StringUtils.isBlank(sign)) {
return APIMessageVo.fail(APIErrorEnum.FAIL_PARA_LOSE.getCode(), APIErrorEnum.FAIL_PARA_LOSE.getName());
}
if(!APP_KEY.equals(app_key)){
return APIMessageVo.fail(APIErrorEnum.FAIL_NOT_EXIST_APP_ID.getCode(), APIErrorEnum.FAIL_NOT_EXIST_APP_ID.getName());
}
//***************sign Calibration ***************
try {
// Get request Parameters in
Map<String, String> sysParams = getSysParams(request, zrsc_param_json);
//SDK Parameter encryption
String signNew = SDKSignUtils.sign(sysParams, APP_SECRET);
// Determine whether the parameter has been changed
if (!sign.equals(signNew)) {
return APIMessageVo.fail(APIErrorEnum.FAIL_ERR_APP_SECRET.getCode(), APIErrorEnum.FAIL_ERR_APP_SECRET.getName());
}
} catch (Exception e) {
return APIMessageVo.fail(APIErrorEnum.FAIL_EXCEPTION.getCode(), APIErrorEnum.FAIL_EXCEPTION.getName());
}
return APIMessageVo.success();
}
2.3 Basic tool classes
APIErrorEnum
public enum APIErrorEnum {
FAIL_NOTAUTH(201," No authorization "),
FAIL_TOKEN_EXPIRE(202,"Token Expired "),
FAIL_PARA_LOSE(203," Missing parameter "),
FAIL_NOT_REALAUTH(204," No real-name authentication passed "),
FAIL_NOT_METHOD(205," Do not have permission to access this interface "),
FAIL_PARA_ERR(206," Incorrect value of parameter "),
FAIL_NOT_EXIST_ACCOUNT(207," User account does not exist "),
FAIL_NOT_FOUND_APPLY(208," Application does not exist "),
FAIL_NOT_PASS_APPROVAL_APPLY(209," Application approval failed "),
FAIL_NOT_EXIST_APP_ID(210,"APP_ID Nonexistent "),
FAIL_NOT_FOUND_INTERFACE(211," Interface does not exist "),
FAIL_ERR_APP_SECRET(212,"appSecret Errors "),
FAIL_CALL_FREQUENTLY(214," Calls too frequently "),
FAIL_EXCEPTION(290," Unknown error ");
private int code;
private String name;
APIErrorEnum(int code,String name) {
this.code = code;
this.name = name;
}
public int getCode() {
return code;
}
public String getName() {
return name;
}
public void setCode(int code) {
this.code = code;
}
public void setName(String name) {
this.name = name;
}
}
APIMessageVo
public class APIMessageVo {
public static final Integer SUCCESS = 100;// Success
private boolean success;// Whether the processing was successful
private Integer code = SUCCESS;// Status code
private String message = " Success ";// Attached message , Such as the reason why the processing result failed, etc.
private Object data="";// You can return the 1 Some result data
public APIMessageVo() {
//default
}
public APIMessageVo(boolean success, Integer code) {
this(success, code, " Success ", null);
}
public APIMessageVo(boolean success, Integer code, String message) {
this(success, code, message, null);
}
public APIMessageVo(boolean success, String message, Object data) {
this.success = success;
this.message = message;
this.data = data;
}
public APIMessageVo(boolean success, Integer code, String message, Object data) {
this.success = success;
this.code = code;
this.message = message;
this.data = data;
}
public APIMessageVo(boolean success, Object data) {
this.success = success;
this.data = data;
}
public static APIMessageVo fail(Integer code) {
return new APIMessageVo(false, code);
}
public static APIMessageVo fail(Integer code,String message) {
return new APIMessageVo(false,code, message);
}
public static APIMessageVo fail(Integer code,String message, Object data) {
return new APIMessageVo(false,code, message, data);
}
public static APIMessageVo success() {
return new APIMessageVo(true, SUCCESS);
}
public static APIMessageVo success(String message) {
return new APIMessageVo(true, message);
}
public static APIMessageVo success(String message, Object data) {
return new APIMessageVo(true, SUCCESS, message, data);
}
public static APIMessageVo success(Object data) {
return new APIMessageVo(true, " Success ", data);
}
}
JsonUtils
public class JsonUtils {
// Definition jackson Object
private static final ObjectMapper MAPPER = new ObjectMapper();
/**
* Object conversion Json
*
* @param obj Object
* @return json String
*/
public static String objToJson(Object obj) {
try {
return MAPPER.writeValueAsString(obj);
} catch (JsonProcessingException e) {
log.error("Json Conversion exception: {}", e);
}
return "Json Conversion exception ";
}
/**
* json Turn object
* @param jsonData json String
* @param beanType Object
* @return Object
*/
public static <T> T jsonToPojo(String jsonData, Class<T> beanType) {
try {
T obj = MAPPER.readValue(jsonData, beanType);
return obj;
} catch (Exception e) {
log.error("Json Conversion exception: {}", e);
}
return null;
}
}
3. SDK code, Java example
DefaultZrscClient
public class DefaultZrscClient implements ZrscClient {
private String serverUrl;
private String accessToken;
private int connectTimeout;
private int readTimeout;
private String appKey;
private String fuzz;
private String appSecret;
public DefaultZrscClient(String serverUrl, String accessToken, String appKey, String appSecret) {
this.connectTimeout = 8000;
this.readTimeout = 8000;
this.serverUrl = serverUrl;
this.accessToken = accessToken;
this.appKey = appKey;
this.appSecret = appSecret;
}
public <T extends AbstractResponse> T execute(ZrscRequest<T> request) throws ZrscException {
try {
String url = this.buildUrl(request);
Map<String, String> params = new HashMap();
String json = request.getAppJsonParams();
params.put("zrsc_param_json", json);
if (request.getOtherParams() != null) {
params.put("other", request.getOtherParams());
}
String rsp = HttpUtil.doPost(url, params, this.connectTimeout, this.readTimeout,this.accessToken);
T resp = this.parse(rsp, request.getResponseClass());
StringBuffer sb = new StringBuffer();
sb.append(url).append("&").append("zrsc_param_json").append("=").append(json);
resp.setUrl(sb.toString());
return resp;
} catch (Exception var8) {
var8.printStackTrace();
throw new ZrscException(" Exception occurred, please try again ");
}
}
private <T extends AbstractResponse> String buildUrl(ZrscRequest<T> request) throws Exception {
Map<String, String> sysParams = request.getSysParams();
Map<String, String> pmap = new TreeMap();
pmap.put("zrsc_param_json", request.getAppJsonParams());
sysParams.put("method", request.getApiMethod());
sysParams.put("access_token", this.accessToken);
sysParams.put("app_key", this.appKey);
pmap.putAll(sysParams);
String sign = this.sign(pmap, this.appSecret);
sysParams.put("sign", sign);
StringBuilder sb = new StringBuilder(this.serverUrl);
sb.append("?");
sb.append(HttpUtil.buildQuery(sysParams, "UTF-8"));
return sb.toString();
}
private <T extends AbstractResponse> T parse(String rsp, Class<T> responseClass) throws ZrscException {
Parser parser;
if (this.serverUrl.endsWith("json")) {
parser = ParserFactory.getJsonParser();
} else {
parser = ParserFactory.getXmlParser();
}
return parser.parse(rsp, responseClass);
}
private String sign(Map<String, String> pmap, String appSecret) throws Exception {
StringBuilder sb = new StringBuilder(appSecret);
Iterator i$ = pmap.entrySet().iterator();
while(i$.hasNext()) {
Map.Entry<String, String> entry = (Map.Entry)i$.next();
String name = (String)entry.getKey();
String value = (String)entry.getValue();
if (StringUtil.areNotEmpty(new String[]{name, value})) {
sb.append(name).append(value);
}
}
sb.append(appSecret);
String result = CodecUtil.md5(sb.toString());
return result;
}
}
public APIMessageVo router(HttpServletRequest request, String zrsc_param_json) {
String access_token = request.getParameter("access_token");
String app_key = request.getParameter("app_key");
String method = request.getParameter("method");
String sign = request.getParameter("sign");
APIMessageVo checkResult=this.routerParaCheck(request, zrsc_param_json,access_token,app_key,method,sign);
if(!checkResult.isSuccess()){// Entry detection failed
return checkResult;
}
if (APPInterfaceNameEnum.API_ADDRESS_ADDRESS2PROVICECITY_GET.getName().equals(method)) {// Get provincial and municipal streets
return this.address2provincecity(zrsc_param_json);
} else {// Interface does not exist
return APIMessageVo.fail(APIErrorEnum.FAIL_NOT_FOUND_INTERFACE.getCode(), APIErrorEnum.FAIL_NOT_FOUND_INTERFACE.getName());
}
}
private APIMessageVo routerParaCheck(HttpServletRequest request, String zrsc_param_json, String access_token,
String app_key, String method, String sign){
//*************** Parameter check ***************
if (StringUtils.isBlank(access_token) || StringUtils.isBlank(app_key) || StringUtils.isBlank(method) ||
StringUtils.isBlank(sign)) {
return APIMessageVo.fail(APIErrorEnum.FAIL_PARA_LOSE.getCode(), APIErrorEnum.FAIL_PARA_LOSE.getName());
}
if(!APP_KEY.equals(app_key)){
return APIMessageVo.fail(APIErrorEnum.FAIL_NOT_EXIST_APP_ID.getCode(), APIErrorEnum.FAIL_NOT_EXIST_APP_ID.getName());
}
//***************sign Calibration ***************
try {
// Get request Parameters in
Map<String, String> sysParams = getSysParams(request, zrsc_param_json);
//SDK Parameter encryption
String signNew = SDKSignUtils.sign(sysParams, APP_SECRET);
// Determine whether the parameter has been changed
if (!sign.equals(signNew)) {
return APIMessageVo.fail(APIErrorEnum.FAIL_ERR_APP_SECRET.getCode(), APIErrorEnum.FAIL_ERR_APP_SECRET.getName());
}
} catch (Exception e) {
return APIMessageVo.fail(APIErrorEnum.FAIL_EXCEPTION.getCode(), APIErrorEnum.FAIL_EXCEPTION.getName());
}
return APIMessageVo.success();
}
0
public APIMessageVo router(HttpServletRequest request, String zrsc_param_json) {
String access_token = request.getParameter("access_token");
String app_key = request.getParameter("app_key");
String method = request.getParameter("method");
String sign = request.getParameter("sign");
APIMessageVo checkResult=this.routerParaCheck(request, zrsc_param_json,access_token,app_key,method,sign);
if(!checkResult.isSuccess()){// Entry detection failed
return checkResult;
}
if (APPInterfaceNameEnum.API_ADDRESS_ADDRESS2PROVICECITY_GET.getName().equals(method)) {// Get provincial and municipal streets
return this.address2provincecity(zrsc_param_json);
} else {// Interface does not exist
return APIMessageVo.fail(APIErrorEnum.FAIL_NOT_FOUND_INTERFACE.getCode(), APIErrorEnum.FAIL_NOT_FOUND_INTERFACE.getName());
}
}
private APIMessageVo routerParaCheck(HttpServletRequest request, String zrsc_param_json, String access_token,
String app_key, String method, String sign){
//*************** Parameter check ***************
if (StringUtils.isBlank(access_token) || StringUtils.isBlank(app_key) || StringUtils.isBlank(method) ||
StringUtils.isBlank(sign)) {
return APIMessageVo.fail(APIErrorEnum.FAIL_PARA_LOSE.getCode(), APIErrorEnum.FAIL_PARA_LOSE.getName());
}
if(!APP_KEY.equals(app_key)){
return APIMessageVo.fail(APIErrorEnum.FAIL_NOT_EXIST_APP_ID.getCode(), APIErrorEnum.FAIL_NOT_EXIST_APP_ID.getName());
}
//***************sign Calibration ***************
try {
// Get request Parameters in
Map<String, String> sysParams = getSysParams(request, zrsc_param_json);
//SDK Parameter encryption
String signNew = SDKSignUtils.sign(sysParams, APP_SECRET);
// Determine whether the parameter has been changed
if (!sign.equals(signNew)) {
return APIMessageVo.fail(APIErrorEnum.FAIL_ERR_APP_SECRET.getCode(), APIErrorEnum.FAIL_ERR_APP_SECRET.getName());
}
} catch (Exception e) {
return APIMessageVo.fail(APIErrorEnum.FAIL_EXCEPTION.getCode(), APIErrorEnum.FAIL_EXCEPTION.getName());
}
return APIMessageVo.success();
}
1
4. Integrate SDK, code example
public APIMessageVo router(HttpServletRequest request, String zrsc_param_json) {
String access_token = request.getParameter("access_token");
String app_key = request.getParameter("app_key");
String method = request.getParameter("method");
String sign = request.getParameter("sign");
APIMessageVo checkResult=this.routerParaCheck(request, zrsc_param_json,access_token,app_key,method,sign);
if(!checkResult.isSuccess()){// Entry detection failed
return checkResult;
}
if (APPInterfaceNameEnum.API_ADDRESS_ADDRESS2PROVICECITY_GET.getName().equals(method)) {// Get provincial and municipal streets
return this.address2provincecity(zrsc_param_json);
} else {// Interface does not exist
return APIMessageVo.fail(APIErrorEnum.FAIL_NOT_FOUND_INTERFACE.getCode(), APIErrorEnum.FAIL_NOT_FOUND_INTERFACE.getName());
}
}
private APIMessageVo routerParaCheck(HttpServletRequest request, String zrsc_param_json, String access_token,
String app_key, String method, String sign){
//*************** Parameter check ***************
if (StringUtils.isBlank(access_token) || StringUtils.isBlank(app_key) || StringUtils.isBlank(method) ||
StringUtils.isBlank(sign)) {
return APIMessageVo.fail(APIErrorEnum.FAIL_PARA_LOSE.getCode(), APIErrorEnum.FAIL_PARA_LOSE.getName());
}
if(!APP_KEY.equals(app_key)){
return APIMessageVo.fail(APIErrorEnum.FAIL_NOT_EXIST_APP_ID.getCode(), APIErrorEnum.FAIL_NOT_EXIST_APP_ID.getName());
}
//***************sign Calibration ***************
try {
// Get request Parameters in
Map<String, String> sysParams = getSysParams(request, zrsc_param_json);
//SDK Parameter encryption
String signNew = SDKSignUtils.sign(sysParams, APP_SECRET);
// Determine whether the parameter has been changed
if (!sign.equals(signNew)) {
return APIMessageVo.fail(APIErrorEnum.FAIL_ERR_APP_SECRET.getCode(), APIErrorEnum.FAIL_ERR_APP_SECRET.getName());
}
} catch (Exception e) {
return APIMessageVo.fail(APIErrorEnum.FAIL_EXCEPTION.getCode(), APIErrorEnum.FAIL_EXCEPTION.getName());
}
return APIMessageVo.success();
}
2
Run results:
data = {"source": "Ejiao Street Dongshou Road North", "province": "Shandong Province", "city": "Liaocheng City", "area": "Dong'e County", "street": "Xincheng Street", "addressInfo": "Ejiao Street Dongshou Road North"}
STEP 5 Summarize
JD.COM open platform in the transmission of reference and signature algorithm is more representative, this blog, just to share the main components of the open platform, I hope you can pay more attention to other content of this site!