关于怎么申请饿百的应用就不一一描述了,这里主要记录代码层次,首先继续往下看的前提是你拥有饿百应用密钥
1、收敛所有Http请求工具类
/**
* @author nanke
* 致终于来到这里的勇敢的人:
* 永远不要放弃!永远不要对自己失望!永远不要逃走辜负了自己。
* 永远不要哭啼!永远不要说再见!永远不要说慌来伤害目己。
* Http网络通信基类
*/
@Slf4j
public class HttpUtil {
private static final CloseableHttpClient httpClient = HttpClients.createDefault();
/**
* 所有对外的Get请求
* @param url 请求接口地址
* @return 接口响应字符串
*/
public static String get(String url) {
HttpGet httpGet = new HttpGet(url);
// 设置超时时间
RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(3000)
.setSocketTimeout(3000).setConnectTimeout(3000).build();
httpGet.setConfig(requestConfig);
// 获取响应
try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
return new BasicResponseHandler().handleResponse(response);
} catch (IOException e) {
} finally {
httpGet.releaseConnection();
}
throw new RuntimeException();
}
/**
* 所有对外的Post请求.
* @param url 请求接口地址
* @param json 请求参数json值
* @return 接口响应字符串
*/
public static String post(String url, String json) {
return post(url,json,null);
}
/**
* 所有对外的Post请求.
* @param url 请求接口地址
* @param json 请求参数json值
* @param contentType 设置请求头内容格式
* @return 接口响应字符串
*/
public static String post(String url, String json, String contentType) {
HttpPost httpPost = new HttpPost(url);
// 设置超时时间
RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(3000)
.setSocketTimeout(3000).setConnectTimeout(3000).build();
httpPost.setConfig(requestConfig);
// 转换json
if (StringUtils.isNotBlank(json)) {
StringEntity entity = new StringEntity(json, Consts.UTF_8);
entity.setContentType("application/json; charset=utf-8");
// 自定义请求头格式
if (StringUtils.isNotBlank(contentType)) {
entity.setContentType(contentType);
}
httpPost.setEntity(entity);
}
try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
return handleResponse(response);
} catch (IOException e) {
e.printStackTrace();
} finally {
httpPost.releaseConnection();
}
throw new RuntimeException();
}
/**
* 处理相应请求
* @param response
* @return
* @throws IOException
*/
public static String handleResponse(HttpResponse response) throws IOException {
StatusLine statusLine = response.getStatusLine();
HttpEntity entity = response.getEntity();
if (statusLine.getStatusCode() >= 300) {
EntityUtils.consume(entity);
throw new HttpResponseException(statusLine.getStatusCode(), statusLine.getReasonPhrase());
} else {
return entity == null ? null : EntityUtils.toString(entity, Consts.UTF_8);
}
}
}
2、封装饿百Http请求工具类
/**
* @author nanke
* 致终于来到这里的勇敢的人:
* 永远不要放弃!永远不要对自己失望!永远不要逃走辜负了自己。
* 永远不要哭啼!永远不要说再见!永远不要说慌来伤害目己。
*/
@Data
public class ELMSysParam {
/**
* 饿了么系统应用appID
*/
private String source;
/**
* 饿了么系统秘钥
*/
private String secret;
}
/**
* @author nanke
* 致终于来到这里的勇敢的人:
* 永远不要放弃!永远不要对自己失望!永远不要逃走辜负了自己。
* 永远不要哭啼!永远不要说再见!永远不要说慌来伤害目己。
*/
public class ELMApiConstant {
/**
* 饿了么基础请求地址前缀
*/
public static final String baseURL = "https://api-be.ele.me/";
/**
* 饿了么请求头内容格式
*/
public static final String headContentType = "application/x-www-form-urlencoded";
}
/**
* @author nanke
* 致终于来到这里的勇敢的人:
* 永远不要放弃!永远不要对自己失望!永远不要逃走辜负了自己。
* 永远不要哭啼!永远不要说再见!永远不要说慌来伤害目己。
*/
public class ELMHttpUtil {
/**
* 饿了么第三方平台交互POST请求入口
* @param param JSON参数
* @param cmd 方法名
* @param sysParam 密钥
* @return
*/
public static String post(String param, String cmd, ELMSysParam sysParam) {
// 设置请求系统参数
HashMap<String, Object> requestMap = new HashMap<>();
requestMap.put("body",JSON.parseObject(param));
requestMap.put("source", sysParam.getSource());
requestMap.put("cmd",cmd);
requestMap.put("timestamp",System.currentTimeMillis() / 1000);
requestMap.put("version",3);
requestMap.put("ticket", UUID.randomUUID().toString().toUpperCase());
requestMap.put("secret", sysParam.getSecret());
requestMap.put("encrypt","");
requestMap.put("sign",sign(requestMap));
String rpcStr = HttpUtil.post(ELMApiConstant.baseURL, getBody(requestMap), ELMApiConstant.headContentType);
return unicodeToString(rpcStr);
}
/**
* 获取请求参数Body
* @param paramMap
* @return
*/
public static String getBody(Map<String,Object> paramMap) {
// 请求参数需要做转换
StringBuilder sb = new StringBuilder();
for (String paramKey : paramMap.keySet()) {
sb.append(paramKey).append("=").append(paramMap.get(paramKey)).append("&");
}
sb.deleteCharAt(sb.length() - 1);
return sb.toString();
}
/**
* 加密
* @param requestMap
* @return
*/
public static String sign(HashMap<String, Object> requestMap) {
// 请求参数排序
Map<String, Object> sortMap = new TreeMap<>(new Comparator<String>() {
@Override
public int compare(String str1, String str2) {
return str1.compareTo(str2);
}
});
sortMap.putAll(requestMap);
String join = Joiner.on("&").withKeyValueSeparator("=").join(sortMap);
return getMd5(join);
}
/**
* 饿了么SDK MD5加密方法
* @param input
* @return
*/
public static String getMd5(String input) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] messageDigest = md.digest(input.getBytes());
BigInteger number = new BigInteger(1, messageDigest);
String hashtext = number.toString(16);
while (hashtext.length() < 32) {
hashtext = "0" + hashtext;
}
return hashtext.toUpperCase();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
/**
* unionCode解码
* @param str
* @return
*/
public static String unicodeToString(String str) {
Pattern pattern = Pattern.compile("(\\\\u(\\p{XDigit}{4}))");
Matcher matcher = pattern.matcher(str);
char ch;
while (matcher.find()) {
ch = (char) Integer.parseInt(matcher.group(2), 16);
str = str.replace(matcher.group(1), ch + "");
}
return str;
}
}
3、封装饿百请求基类
/**
* @author nanke
* 致终于来到这里的勇敢的人:
* 永远不要放弃!永远不要对自己失望!永远不要逃走辜负了自己。
* 永远不要哭啼!永远不要说再见!永远不要说慌来伤害目己。
*/
@Data
@Slf4j
@NoArgsConstructor
public class ELMBaseRequest {
/**
* 请求方法
*/
private String cmd;
/**
* 系统参数
*/
private ELMSysParam sysParam;
public ELMBaseRequest(String cmd,ELMSysParam sysParam) {
this.sysParam = sysParam;
this.cmd = cmd;
}
/**
* 通用日志请求Request方法
* @return
*/
public String doRequest() {
// 反射获取json参数
String param = this.constructParam();
try {
return ELMHttpUtil.post(param,this.cmd,this.sysParam);
} catch (Exception e) {
log.warn("饿了么请求发生异常,入参:{},cmd:{},系统参数:{}",param,this.cmd, JSON.toJSONString(sysParam),e);
}
return null;
}
private static Set<Class<?>> BASIC_PARAM_TYPE_SET = new HashSet<>();
static {
BASIC_PARAM_TYPE_SET.add(Boolean.TYPE);
BASIC_PARAM_TYPE_SET.add(Boolean.class);
BASIC_PARAM_TYPE_SET.add(Integer.TYPE);
BASIC_PARAM_TYPE_SET.add(Integer.class);
BASIC_PARAM_TYPE_SET.add(Long.TYPE);
BASIC_PARAM_TYPE_SET.add(Long.class);
BASIC_PARAM_TYPE_SET.add(Float.TYPE);
BASIC_PARAM_TYPE_SET.add(Float.class);
BASIC_PARAM_TYPE_SET.add(Double.TYPE);
BASIC_PARAM_TYPE_SET.add(Double.class);
BASIC_PARAM_TYPE_SET.add(String.class);
}
/**
* 反射获取自定义字段属性值
* @return
*/
private String constructParam() {
try {
JSONObject param = new JSONObject();
Field[] fields = this.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
Class<?> typeClass = field.getType();
String paramName = field.getName();
Object paramValue = field.get(this);
if (paramValue != null) {
if (BASIC_PARAM_TYPE_SET.contains(typeClass)) {
param.put(paramName, String.valueOf(paramValue));
} else {
param.put(paramName, paramValue);
}
}
}
return param.toJSONString();
} catch (Exception var1) {
throw new RuntimeException(var1);
}
}
}
4、封装饿百返回对象
/**
* @author nanke
* 致终于来到这里的勇敢的人:
* 永远不要放弃!永远不要对自己失望!永远不要逃走辜负了自己。
* 永远不要哭啼!永远不要说再见!永远不要说慌来伤害目己。
*/
@Data
public class ELMHttpRDTO <T> {
/**
* 返回参数
*/
private ELMBody<T> body;
/**
* 响应CMD
*/
private String cmd;
/**
* 签名
*/
private String sign;
/**
* 美团AppId
*/
private String source;
/**
* 随机戳
*/
private String ticket;
/**
* 时间戳
*/
private Long timestamp;
/**
* 版本
*/
private Integer version;
@Data
public static class ELMBody <T> {
/**
* 数据
*/
public T data;
/**
* 错误码
*/
public Integer errno;
/**
* 错误描述
*/
public String error;
}
public boolean success() {
return getBody() != null && "success".equals(getBody().getError());
}
}
5、演示(获取商品详情)
Api地址:https://open-retail.ele.me/#/apidoc/me.ele.retail:sku.list-3?aopApiCategory=item_all&type=api_menu
1、创建Request,继承请求基类
/**
* @author nanke
* @date 2021/4/22 上午10:44
* 致终于来到这里的勇敢的人:
* 永远不要放弃!永远不要对自己失望!永远不要逃走辜负了自己。
* 永远不要哭啼!永远不要说再见!永远不要说慌来伤害目己。
*/
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class ELMSkuInfoRequest extends ELMBaseRequest {
/**
* 合作方门店ID
*/
private String shop_id;
/**
* 商品自定义ID
*/
private String custom_sku_id;
public ELMSkuInfoRequest(ELMSysParam sysParam) {
super("sku.list", sysParam);
}
}
2、定义返回对象
/**
* @author nanke
* 致终于来到这里的勇敢的人:
* 永远不要放弃!永远不要对自己失望!永远不要逃走辜负了自己。
* 永远不要哭啼!永远不要说再见!永远不要说慌来伤害目己。
*/
@Data
public class ELMSkuDetail {
/**
* 商品自定义ID
*/
private String custom_sku_id;
/**
* 商品名
*/
private String name;
/**
* 售价 分
*/
private Long sale_price;
/**
* 库存 范围:0~9999
*/
private Integer left_num;
}
/**
* @author nanke
* 致终于来到这里的勇敢的人:
* 永远不要放弃!永远不要对自己失望!永远不要逃走辜负了自己。
* 永远不要哭啼!永远不要说再见!永远不要说慌来伤害目己。
*/
@Data
public class ELMSkuListResp {
/**
* 商品数据列表
*/
private List<ELMSkuDetail> list;
}
3、测试
public static void main(String[] args) {
ELMSysParam param = new ELMSysParam();
param.setSource("***");
param.setSecret("***");
ELMSkuInfoRequest request = new ELMSkuInfoRequest(param);
request.setShop_id("158");
request.setCustom_sku_id("15");
String rpcStr = request.doRequest();
if (StringUtils.isNotBlank(rpcStr)) {
ELMHttpRDTO<ELMSkuListResp> rpcRDTO = parseBody(rpcStr, new TypeReference<ELMHttpRDTO<ELMSkuListResp>>() {});
if (rpcRDTO.success()) {
List<ELMSkuDetail> list = rpcRDTO.getBody().getData().getList();
log.info("饿了么查询门店商品详情,门店:{},SkuId:{},Info:{}",request.getShop_id(),request.getCustom_sku_id(),JSON.toJSONString(list.get(0)));
}
}
log.error("饿了么查询门店商品详情失败,执行体:{},返回值:{}", JSON.toJSONString(request),rpcStr);
}
private static <Z> Z parseBody(String jsonStr, TypeReference<Z> reference) {
return JSONObject.parseObject(jsonStr,reference);
}