skyline ad75507725 日期格式优化,开关门记录 преди 1 месец
..
src ad75507725 日期格式优化,开关门记录 преди 1 месец
EXAMPLES.md a5830551be 按照https://showdoc.hahabianli.com/web/#/685869388/275897889开发哈哈JAVA-SDK преди 4 месеца
README.md 971379a887 优化 преди 3 месеца
pom.xml de25e04cfc 优化 преди 3 месеца

README.md

哈哈零售 Java SDK

License Java Maven

哈哈零售系统 Java SDK,为智能视觉识别售卖机系统提供完整的API接口封装。

📋 目录


功能特性

完整接口覆盖 - 支持哈哈零售平台全部31个API接口
自动令牌管理 - 自动获取、刷新和管理access_token(15天有效期)
自动签名 - 内置MD5签名算法,无需手动处理
类型安全 - 提供完整的类型定义和泛型支持
日志支持 - 集成SLF4J日志框架
连接池管理 - 基于OkHttp的高性能HTTP客户端


快速开始

1. Maven依赖

<dependency>
    <groupId>com.haha</groupId>
    <artifactId>haha-sdk</artifactId>
    <version>1.0.0</version>
</dependency>

2. 初始化SDK

import com.haha.sdk.HahaClient;
import com.haha.sdk.config.HahaConfig;

// 创建配置
HahaConfig config = HahaConfig.builder()
    .apiBaseUrl("http://api.hahabianli.com")  // API地址(默认值)
    .appId("your_app_id")                      // 商家AppId
    .appSecret("your_app_secret")              // 商家AppSecret
    .connectTimeout(10)                        // 连接超时(秒)
    .readTimeout(30)                           // 读取超时(秒)
    .build();

// 创建客户端
HahaClient client = new HahaClient(config);

// 使用完毕后关闭(可选)
// client.shutdown();

3. 快速调用示例

import com.haha.sdk.exception.HahaException;

try {
    // 获取设备列表
    List<DeviceInfo> devices = client.getDeviceApi().getDeviceList(1, 20);
    
    // 开门
    OpenDoorResult result = client.getDeviceApi()
        .openDoor("device001", "ORDER" + System.currentTimeMillis(), null);
    System.out.println("订单号: " + result.getOrderNo());
    
} catch (HahaException e) {
    System.err.println("错误: " + e.getMessage());
}

核心功能

1. 设备管理

通过 client.getDeviceApi() 访问设备相关接口:

1.1 获取设备列表

// 获取第1页,每页20条
List<DeviceInfo> devices = client.getDeviceApi().getDeviceList(1, 20);

for (DeviceInfo device : devices) {
    System.out.println("设备ID: " + device.getId());
    System.out.println("设备名称: " + device.getName());
    System.out.println("设备地址: " + device.getAddress());
    System.out.println("设备状态: " + device.getStatus()); // 1-正常, 2-冻结
}

1.2 查询设备是否多门单开

String deviceId = "device001";
Integer multiDoorType = client.getDeviceApi().isMultiDoorUnique(deviceId);

// 返回值:0-非多门单开,2-双门单开,3-三门单开,4-四门单开
if (multiDoorType == 2) {
    System.out.println("这是双门单开设备");
}

1.3 设备开门

String deviceId = "device001";
String outTradeNo = "ORDER" + System.currentTimeMillis(); // 商户订单号
Integer doorIndex = null; // 多门单开时必传:0-A门,1-B门

OpenDoorResult result = client.getDeviceApi().openDoor(deviceId, outTradeNo, doorIndex);
System.out.println("哈哈平台订单号: " + result.getOrderNo());

1.4 查询设备在线状态

DeviceOnlineStatus status = client.getDeviceApi().getOnlineStatus("device001");

System.out.println("在线状态: " + status.getOnlineStatus()); // 0-离线, 1-在线
System.out.println("最后在线时间: " + status.getLastOnlineTime());

1.5 设置设备音量

// 音量范围:0-100,0表示静音
boolean success = client.getDeviceApi().setVolume("device001", 80);

1.6 查询设备和锁的状态

Map<String, Object> status = client.getDeviceApi().getDeviceStatus("device001");

System.out.println("设备状态: " + status.get("device_status")); // 0-离线, 1-在线, 2-故障
System.out.println("门状态: " + status.get("door_status"));     // 0-关闭, 1-打开
System.out.println("锁状态: " + status.get("lock_status"));     // 0-未锁, 1-已锁
System.out.println("摄像头: " + status.get("camera_status"));   // 0-异常, 1-正常
System.out.println("网络: " + status.get("network_status"));    // 0-断开, 1-连接

2. 商品管理

通过 client.getGoodsApi() 访问商品相关接口:

2.1 获取设备可售卖商品列表

List<Map<String, Object>> goodsList = client.getGoodsApi()
    .getDeviceGoodsList("device001");

for (Map<String, Object> goods : goodsList) {
    System.out.println("商品ID: " + goods.get("goods_id"));
    System.out.println("商品名: " + goods.get("goods_name"));
    System.out.println("价格: " + goods.get("price"));
    System.out.println("库存: " + goods.get("stock"));
}

2.2 获取商品总库

// 分页查询,支持关键词搜索
Map<String, Object> result = client.getGoodsApi()
    .getTotalList(1, 20, "可乐");

int total = (int) result.get("total");
List<Map<String, Object>> list = (List<Map<String, Object>>) result.get("list");

2.3 添加商品至商家商品库

String goodsId = "goods001";  // 来自商品总库的商品ID
String price = "3.50";        // 售价

boolean success = client.getGoodsApi().addToMerchant(goodsId, price);

2.4 获取商家商品库

Map<String, Object> result = client.getGoodsApi().getMerchantList(1, 20);

int total = (int) result.get("total");
List<Map<String, Object>> list = (List<Map<String, Object>>) result.get("list");

2.5 商品上下架

String deviceId = "device001";
String goodsId = "goods001";
int status = 1; // 0-下架, 1-上架

boolean success = client.getGoodsApi().setStatus(deviceId, goodsId, status);

2.6 获取和更新设备层模板

// 获取层模板
Map<String, Object> template = client.getGoodsApi().getLayerTemplate("device001");

// 更新层模板(layers为JSON格式的层级配置)
String layersJson = "[{\"layer_no\":1,\"layer_name\":\"第一层\",\"goods_list\":[]}]";
boolean success = client.getGoodsApi().updateLayerTemplate("device001", layersJson);

2.7 新品申请

boolean success = client.getGoodsApi().applyNew(
    "新商品名称",
    "6901234567890",
    "http://example.com/image.jpg",
    "商品描述(可选)"
);

2.8 查询商品编号对应关系

// 通过商家商品ID查询
Map<String, Object> mapping = client.getGoodsApi()
    .getIdMapping("merchant_001", null);

// 或通过哈哈平台商品ID查询
mapping = client.getGoodsApi().getIdMapping(null, "haha_001");

2.9 商品合并

String targetGoodsId = "goods001";           // 保留的商品
String sourceGoodsIds = "goods002,goods003"; // 要合并的商品(逗号分隔)

boolean success = client.getGoodsApi().mergeGoods(targetGoodsId, sourceGoodsIds);

3. 订单管理

通过 client.getOrderApi() 访问订单相关接口:

3.1 查询识别结果

// 方式1:通过哈哈平台订单号查询
Map<String, Object> result = client.getOrderApi()
    .getRecognizeResult("HH202401240001", null);

// 方式2:通过商户订单号查询
result = client.getOrderApi()
    .getRecognizeResult(null, "ORDER123456");

// 解析结果
List<Map<String, Object>> goodsList = (List) result.get("goods_list");
Double totalAmount = (Double) result.get("total_amount");
Double confidence = (Double) result.get("confidence");
String videoUrl = (String) result.get("video_url");

System.out.println("总金额: " + totalAmount);
System.out.println("置信度: " + confidence);

3.2 查询订单详情

Map<String, Object> order = client.getOrderApi()
    .queryOrder("HH202401240001", null);

String orderStatus = (String) order.get("order_status"); // paying, paid, refund, closed
System.out.println("订单状态: " + orderStatus);

3.3 设置订单支付状态

String orderNo = "HH202401240001";
int payStatus = 1; // 1-支付成功, 2-支付失败
String payTime = "2024-01-24 15:30:00";
String transactionId = "WX123456789"; // 第三方支付流水号

boolean success = client.getOrderApi()
    .setPayStatus(orderNo, payStatus, payTime, transactionId);

3.4 获取开门前后图片或视频

Map<String, Object> media = client.getOrderApi()
    .getOrderMedia("HH202401240001");

String beforeImage = (String) media.get("before_image");
String afterImage = (String) media.get("after_image");
String videoUrl = (String) media.get("video_url");

3.5 查询回调状态

Map<String, Object> callbackStatus = client.getOrderApi()
    .getCallbackStatus("HH202401240001");

int status = (int) callbackStatus.get("callback_status"); // 0-未推送, 1-成功, 2-失败
int retryCount = (int) callbackStatus.get("retry_count");

3.6 获取静态柜分层识别结果

Map<String, Object> layerResult = client.getOrderApi()
    .getLayerRecognize("HH202401240001");

List<Map<String, Object>> layers = (List) layerResult.get("layers");
for (Map<String, Object> layer : layers) {
    int layerNo = (int) layer.get("layer_no");
    String beforeImage = (String) layer.get("before_image");
    String afterImage = (String) layer.get("after_image");
    List<Map<String, Object>> goodsList = (List) layer.get("goods_list");
}

高级用法

手动管理access_token

SDK会自动管理token,但如果需要手动设置:

// 手动设置token(如果你已经有token并自行管理)
client.setAccessToken("your_access_token", 1296000); // 15天有效期(秒)

// 或者让SDK自动获取token
String token = client.getAccessToken();

自定义HTTP配置

HahaConfig config = HahaConfig.builder()
    .apiBaseUrl("http://api.hahabianli.com")
    .appId("your_app_id")
    .appSecret("your_app_secret")
    .connectTimeout(15)    // 连接超时15秒
    .readTimeout(60)       // 读取超时60秒
    .writeTimeout(60)      // 写入超时60秒
    .enableLog(true)       // 启用日志
    .build();

HahaClient client = new HahaClient(config);

资源释放

// 程序退出前关闭客户端,释放连接池资源
client.shutdown();

异常处理

SDK统一使用 HahaException 异常:

import com.haha.sdk.exception.HahaException;

try {
    OpenDoorResult result = client.getDeviceApi()
        .openDoor("device001", "ORDER001", null);
    
} catch (HahaException e) {
    // 错误码(对应API文档的错误码)
    Integer errorCode = e.getCode();
    
    // 错误信息
    String errorMsg = e.getMessage();
    
    System.err.println("错误码: " + errorCode + ", 错误信息: " + errorMsg);
    
    // 如果需要查看底层异常
    if (e.getCause() != null) {
        e.getCause().printStackTrace();
    }
}

常见错误码

错误码 说明 处理方案
1 SUCCESS 操作成功
0 FAIL 操作失败
-1 参数错误 检查请求参数
-2 签名错误 检查AppSecret
-3 token无效 重新获取token
-4 token过期 SDK会自动刷新
-100 设备不存在 检查设备ID
-101 设备离线 等待设备上线
-103 设备使用中 等待购物结束

完整接口列表

设备接口(9个)

方法 说明
getDeviceList 获取设备列表
isMultiDoorUnique 查询是否多门单开
openDoor 设备开门
getOnlineStatus 查询在线状态
setVolume 设置音量
getDeviceStatus 查询设备和锁状态

商品接口(10个)

方法 说明
getDeviceGoodsList 设备可售商品列表
getTotalList 商品总库列表
addToMerchant 添加至商家库
getMerchantList 商家商品库列表
setStatus 商品上下架
getLayerTemplate 获取层模板
updateLayerTemplate 更新层模板
applyNew 新品申请
getIdMapping 商品ID对应关系
mergeGoods 商品合并

订单接口(8个)

方法 说明
getRecognizeResult 查询识别结果
queryOrder 查询订单详情
setPayStatus 设置支付状态
getOrderMedia 获取图片/视频
getCallbackStatus 查询回调状态
getLayerRecognize 静态柜分层结果

常见问题

Q1: access_token有效期多久?

A: 15天(1296000秒)。SDK会自动管理,到期前2天内会自动刷新。

Q2: 如何处理识别结果通知?

A: 哈哈平台会通过回调地址推送识别结果。商户需要:

  1. 在商家后台配置回调地址
  2. 接收POST通知
  3. 根据商品列表扣款
  4. 调用setPayStatus接口告知支付结果

Q3: 识别置信度低于0.8怎么办?

A: 建议通过getOrderMedia接口获取购物视频进行人工审核。

Q4: 多门柜如何开门?

A: 先调用isMultiDoorUnique判断设备类型,如果返回2(双门),开门时需传递doorIndex参数(0或1)。

Q5: SDK是否线程安全?

A: 是的。HahaClient可以在多线程环境中安全使用,建议作为单例管理。


技术支持


开源协议

Apache License 2.0


版本: 1.0.0
更新时间: 2024-01-24