第一次对接美团开放平台API时,我花了整整三天时间才搞明白整个流程。现在回想起来,其实关键点就几个,但当时确实踩了不少坑。美团API主要分为外卖、到店、酒店等不同业务线,我们今天重点讲外卖业务中最常用的商品列表接口对接。
要调用美团API,首先得在美团开放平台(open.meituan.com)完成开发者注册。注册时需要准备营业执照、法人身份证等材料,审核通常需要1-3个工作日。审核通过后,在"应用管理"页面可以找到你的app_id和app_secret,这两个参数相当于你的账号密码,千万要保管好。
我建议先在沙箱环境测试,美团提供了完整的沙箱环境,地址是open-erp.meituan.com。沙箱环境不会产生真实订单,适合调试接口。等全部调通后再切换到生产环境,这样可以避免很多不必要的麻烦。
美团API调用最关键的环节就是签名(sig)生成,这也是新手最容易出错的地方。签名需要三个基础参数:
时间戳获取要注意时区问题,我推荐用Java 8的ZonedDateTime:
java复制ZoneId zone = ZoneId.of("Asia/Shanghai");
long timestamp = ZonedDateTime.now(zone).toEpochSecond();
门店编码可以在美团商家后台找到,每个门店都有唯一的poi_code。这三个参数需要按特定顺序拼接成字符串,顺序错了签名肯定对不上。
美团使用的是MD5签名算法,具体步骤是:
app_id=xxx&app_poi_code=xxx×tamp=xxx格式拼接&app_secret=你的密钥这里有个坑:拼接时参数值必须原样传递,不能做URL编码。我封装了一个签名工具类:
java复制public class SignUtil {
public static String generateSig(String appId, String poiCode,
long timestamp, String secret) {
String baseString = "app_id=" + appId +
"&app_poi_code=" + poiCode +
"×tamp=" + timestamp +
"&app_secret=" + secret;
return DigestUtils.md5Hex(baseString);
}
}
测试时可以用美团提供的签名校验工具验证你的签名是否正确。如果返回"签名验证通过",就可以进行下一步了。
以获取商品列表接口/food/list为例,最终请求URL需要包含以下参数:
完整URL格式如下:
code复制https://waimaiopen.meituan.com/api/v1/food/list?
app_id=你的APPID&
app_poi_code=门店编码&
timestamp=时间戳&
sig=生成的签名
建议使用HttpClient发送GET请求,代码示例:
java复制CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
String result = EntityUtils.toString(response.getEntity());
// 处理返回结果
}
美团API返回的是JSON格式数据,但有个特殊之处:实际数据被包裹在一个JSONP回调函数中。比如返回可能是:
code复制callback({"data":[...]})
需要先去掉外层的回调函数包装:
java复制if (result.startsWith("callback(")) {
result = result.substring(9, result.length() - 1);
}
然后就可以用Jackson或Fastjson解析了。建议先定义对应的Java实体类:
java复制public class FoodItem {
private Long app_food_code;
private String name;
private Float price;
// 其他字段及getter/setter
}
public class ApiResponse {
private List<FoodItem> data;
// getter/setter
}
解析代码:
java复制ObjectMapper mapper = new ObjectMapper();
ApiResponse response = mapper.readValue(result, ApiResponse.class);
List<FoodItem> foodList = response.getData();
存储美团商品数据至少需要两张表:
建表SQL示例:
sql复制CREATE TABLE meituan_foods (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
app_food_code BIGINT COMMENT '美团商品ID',
name VARCHAR(100) COMMENT '商品名称',
price DECIMAL(10,2) COMMENT '价格',
category VARCHAR(50) COMMENT '分类',
picture_url VARCHAR(255) COMMENT '图片URL',
is_sold_out TINYINT COMMENT '是否售罄',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE meituan_skus (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
food_id BIGINT COMMENT '关联商品ID',
sku_id VARCHAR(50) COMMENT 'SKU编码',
spec VARCHAR(100) COMMENT '规格',
price DECIMAL(10,2) COMMENT '价格',
stock INT COMMENT '库存'
);
我推荐采用增量同步策略,每次只同步变更的数据。美团API返回的数据中有utime(更新时间戳)字段,可以基于这个字段做增量查询。
同步代码逻辑:
java复制public void syncFoodData(List<FoodItem> newData) {
// 1. 查询现有数据
Map<Long, FoodItem> existingMap = queryExistingFoods();
// 2. 遍历新数据
for (FoodItem item : newData) {
if (existingMap.containsKey(item.getApp_food_code())) {
// 更新操作
updateFood(item);
} else {
// 新增操作
insertFood(item);
}
// 同步SKU数据
syncSkus(item.getSkus(), item.getApp_food_code());
}
// 3. 处理下架商品(可选)
handleRemovedItems(newData, existingMap.keySet());
}
美团API调用常见异常包括:
建议对每种异常做专门处理:
java复制try {
// 调用API
} catch (MeituanApiException e) {
switch (e.getCode()) {
case 1001:
logger.error("签名错误,请检查签名生成逻辑");
break;
case 40001:
logger.warn("调用频率超限,10秒后重试");
Thread.sleep(10000);
retry();
break;
default:
logger.error("美团API异常", e);
}
}
在实际项目中,我发现美团API的稳定性有几个关键点需要注意。首先是时间戳的有效期只有5分钟,超过这个时间请求会被拒绝。其次是门店编码(app_poi_code)一定要和签约时的一致,否则会报权限错误。
对于高频调用的场景,建议做以下优化:
一个实用的重试机制实现:
java复制public <T> T executeWithRetry(Callable<T> task, int maxRetry) {
int retryCount = 0;
while (retryCount < maxRetry) {
try {
return task.call();
} catch (RateLimitException e) {
retryCount++;
Thread.sleep(1000 * retryCount); // 指数退避
}
}
throw new RuntimeException("重试次数超过限制");
}
最后提醒一点,美团API的响应数据量可能很大,特别是商品列表接口。我遇到过单次返回2MB数据的情况,所以要做好内存管理和流式处理,避免OOM错误。