本文档提供完整的SDK使用示例,涵盖从初始化到实际业务场景的各种用法。
import com.haha.sdk.HahaClient;
import com.haha.sdk.config.HahaConfig;
import com.haha.sdk.exception.HahaException;
public class HahaSDKExample {
public static void main(String[] args) {
// 创建配置
HahaConfig config = HahaConfig.builder()
.apiBaseUrl("http://api.hahabianli.com")
.appId("your_app_id")
.appSecret("your_app_secret")
.connectTimeout(10)
.readTimeout(30)
.build();
// 验证配置
config.validate();
// 创建客户端
HahaClient client = new HahaClient(config);
try {
// 测试获取access_token
String token = client.getAccessToken();
System.out.println("获取Token成功: " + token);
} catch (HahaException e) {
System.err.println("初始化失败: " + e.getMessage());
} finally {
// 关闭客户端(可选)
client.shutdown();
}
}
}
import com.haha.sdk.HahaClient;
import com.haha.sdk.config.HahaConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class HahaSDKConfig {
@Value("${haha.api.baseUrl}")
private String apiBaseUrl;
@Value("${haha.api.appId}")
private String appId;
@Value("${haha.api.appSecret}")
private String appSecret;
@Bean
public HahaClient hahaClient() {
HahaConfig config = HahaConfig.builder()
.apiBaseUrl(apiBaseUrl)
.appId(appId)
.appSecret(appSecret)
.build();
return new HahaClient(config);
}
}
application.yml配置:
haha:
api:
baseUrl: http://api.hahabianli.com
appId: your_app_id
appSecret: your_app_secret
import com.haha.sdk.model.DeviceInfo;
import java.util.List;
public class DeviceListExample {
public void listAllDevices(HahaClient client) {
try {
// 获取第一页
List<DeviceInfo> devices = client.getDeviceApi().getDeviceList(1, 20);
System.out.println("=== 设备列表 ===");
for (DeviceInfo device : devices) {
System.out.println("--------------------");
System.out.println("设备ID: " + device.getId());
System.out.println("设备名称: " + device.getName());
System.out.println("设备地址: " + device.getAddress());
System.out.println("设备状态: " + getStatusText(device.getStatus()));
}
} catch (HahaException e) {
System.err.println("获取设备列表失败: " + e.getMessage());
}
}
private String getStatusText(String status) {
return "1".equals(status) ? "正常" : "冻结";
}
}
import com.haha.sdk.model.OpenDoorResult;
import com.haha.sdk.model.DeviceOnlineStatus;
public class OpenDoorExample {
public void openDoorWithCheck(HahaClient client, String deviceId) {
try {
// 1. 检查设备在线状态
DeviceOnlineStatus status = client.getDeviceApi().getOnlineStatus(deviceId);
if (status.getOnlineStatus() != 1) {
System.out.println("设备离线,无法开门");
System.out.println("最后在线时间: " + status.getLastOnlineTime());
return;
}
// 2. 检查是否多门单开
Integer multiDoorType = client.getDeviceApi().isMultiDoorUnique(deviceId);
Integer doorIndex = null;
if (multiDoorType == 2) {
// 双门柜,需要指定开哪个门
doorIndex = 0; // 0-A门, 1-B门
System.out.println("这是双门柜,将打开A门");
}
// 3. 生成商户订单号
String outTradeNo = "ORDER_" + System.currentTimeMillis();
// 4. 开门
OpenDoorResult result = client.getDeviceApi()
.openDoor(deviceId, outTradeNo, doorIndex);
System.out.println("开门成功!");
System.out.println("商户订单号: " + outTradeNo);
System.out.println("哈哈订单号: " + result.getOrderNo());
// 5. 保存订单号,用于后续查询识别结果
saveOrderInfo(outTradeNo, result.getOrderNo());
} catch (HahaException e) {
System.err.println("开门失败: " + e.getMessage());
}
}
private void saveOrderInfo(String outTradeNo, String orderNo) {
// 保存到数据库
System.out.println("订单信息已保存");
}
}
import java.util.Map;
public class DeviceMonitorExample {
public void monitorDevice(HahaClient client, String deviceId) {
try {
// 获取设备详细状态
Map<String, Object> status = client.getDeviceApi().getDeviceStatus(deviceId);
int deviceStatus = (int) status.get("device_status");
int doorStatus = (int) status.get("door_status");
int lockStatus = (int) status.get("lock_status");
int cameraStatus = (int) status.get("camera_status");
int networkStatus = (int) status.get("network_status");
System.out.println("=== 设备状态报告 ===");
System.out.println("设备ID: " + deviceId);
System.out.println("设备状态: " + getDeviceStatusText(deviceStatus));
System.out.println("门状态: " + (doorStatus == 1 ? "打开" : "关闭"));
System.out.println("锁状态: " + (lockStatus == 1 ? "已锁" : "未锁"));
System.out.println("摄像头: " + (cameraStatus == 1 ? "正常" : "异常"));
System.out.println("网络: " + (networkStatus == 1 ? "连接" : "断开"));
// 异常告警
if (deviceStatus == 2) {
System.err.println("⚠️ 警告:设备故障,需要维护!");
}
if (cameraStatus == 0) {
System.err.println("⚠️ 警告:摄像头异常,可能影响识别!");
}
} catch (HahaException e) {
System.err.println("获取设备状态失败: " + e.getMessage());
}
}
private String getDeviceStatusText(int status) {
switch (status) {
case 0: return "离线";
case 1: return "在线";
case 2: return "故障";
default: return "未知";
}
}
}
import java.util.List;
import java.util.Map;
public class GoodsManagementExample {
// 从总库添加商品到商家库
public void addGoodsToMerchant(HahaClient client) {
try {
// 1. 搜索商品总库
Map<String, Object> result = client.getGoodsApi()
.getTotalList(1, 20, "可乐");
List<Map<String, Object>> list = (List) result.get("list");
if (list.isEmpty()) {
System.out.println("未找到商品");
return;
}
// 2. 选择第一个商品
Map<String, Object> goods = list.get(0);
String goodsId = (String) goods.get("goods_id");
String goodsName = (String) goods.get("goods_name");
System.out.println("找到商品: " + goodsName);
// 3. 添加到商家库,设置价格
String price = "3.50";
boolean success = client.getGoodsApi().addToMerchant(goodsId, price);
if (success) {
System.out.println("商品已添加到商家库,售价: " + price);
}
} catch (HahaException e) {
System.err.println("操作失败: " + e.getMessage());
}
}
// 设备商品上架
public void setupDeviceGoods(HahaClient client, String deviceId) {
try {
// 1. 获取商家商品库
Map<String, Object> result = client.getGoodsApi().getMerchantList(1, 100);
List<Map<String, Object>> goodsList = (List) result.get("list");
System.out.println("商家商品库共有 " + goodsList.size() + " 个商品");
// 2. 将商品上架到指定设备
for (Map<String, Object> goods : goodsList) {
String goodsId = (String) goods.get("goods_id");
String goodsName = (String) goods.get("goods_name");
// 上架
boolean success = client.getGoodsApi().setStatus(deviceId, goodsId, 1);
if (success) {
System.out.println("✓ " + goodsName + " 已上架");
}
}
} catch (HahaException e) {
System.err.println("上架失败: " + e.getMessage());
}
}
}
public class NewGoodsExample {
public void applyNewGoods(HahaClient client, String barcode, String name, String imageUrl) {
try {
// 1. 先查询商品是否已存在
Map<String, Object> existingGoods = searchGoodsByBarcode(client, barcode);
if (existingGoods != null) {
System.out.println("商品已存在: " + existingGoods.get("goods_name"));
return;
}
// 2. 提交新品申请
String description = "这是一款新商品";
boolean success = client.getGoodsApi()
.applyNew(name, barcode, imageUrl, description);
if (success) {
System.out.println("新品申请已提交,等待审核");
System.out.println("商品名称: " + name);
System.out.println("商品条码: " + barcode);
}
} catch (HahaException e) {
System.err.println("申请失败: " + e.getMessage());
}
}
private Map<String, Object> searchGoodsByBarcode(HahaClient client, String barcode) {
try {
Map<String, Object> result = client.getGoodsApi()
.getTotalList(1, 10, barcode);
List<Map<String, Object>> list = (List) result.get("list");
return list.isEmpty() ? null : list.get(0);
} catch (HahaException e) {
return null;
}
}
}
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
public class OrderRecognizeExample {
// 模拟接收哈哈平台的识别结果通知
public void handleRecognizeCallback(HahaClient client, String orderNo) {
try {
// 1. 查询识别结果
Map<String, Object> result = client.getOrderApi()
.getRecognizeResult(orderNo, null);
// 2. 解析识别结果
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("=== 识别结果 ===");
System.out.println("订单号: " + orderNo);
System.out.println("总金额: " + totalAmount);
System.out.println("置信度: " + confidence);
// 3. 显示商品明细
System.out.println("\n商品明细:");
for (Map<String, Object> goods : goodsList) {
String goodsName = (String) goods.get("goods_name");
int quantity = (int) goods.get("quantity");
double price = (double) goods.get("price");
double amount = (double) goods.get("amount");
System.out.println(" " + goodsName + " x" + quantity + " = ¥" + amount);
}
// 4. 判断是否需要人工审核
if (confidence < 0.8) {
System.out.println("\n⚠️ 置信度较低,建议人工审核");
System.out.println("视频地址: " + videoUrl);
// 可以通过getOrderMedia获取更多图片
Map<String, Object> media = client.getOrderApi().getOrderMedia(orderNo);
System.out.println("开门前图片: " + media.get("before_image"));
System.out.println("关门后图片: " + media.get("after_image"));
return;
}
// 5. 置信度高,直接扣款
boolean paySuccess = processPayment(orderNo, new BigDecimal(totalAmount));
// 6. 通知哈哈平台支付结果
int payStatus = paySuccess ? 1 : 2;
String payTime = getCurrentTime();
String transactionId = "PAY_" + System.currentTimeMillis();
client.getOrderApi().setPayStatus(orderNo, payStatus, payTime, transactionId);
if (paySuccess) {
System.out.println("\n✓ 支付成功");
} else {
System.out.println("\n✗ 支付失败");
}
} catch (HahaException e) {
System.err.println("处理识别结果失败: " + e.getMessage());
}
}
private boolean processPayment(String orderNo, BigDecimal amount) {
// 调用第三方支付接口扣款
System.out.println("正在扣款 ¥" + amount + "...");
return true; // 模拟支付成功
}
private String getCurrentTime() {
return new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
.format(new java.util.Date());
}
}
public class OrderQueryExample {
public void queryAndVerifyOrder(HahaClient client, String orderNo) {
try {
// 1. 查询订单详情
Map<String, Object> order = client.getOrderApi().queryOrder(orderNo, null);
String outTradeNo = (String) order.get("out_trade_no");
String deviceId = (String) order.get("device_id");
String orderStatus = (String) order.get("order_status");
Double totalAmount = (Double) order.get("total_amount");
String createTime = (String) order.get("create_time");
String payTime = (String) order.get("pay_time");
System.out.println("=== 订单详情 ===");
System.out.println("哈哈订单号: " + orderNo);
System.out.println("商户订单号: " + outTradeNo);
System.out.println("设备ID: " + deviceId);
System.out.println("订单状态: " + getOrderStatusText(orderStatus));
System.out.println("订单金额: ¥" + totalAmount);
System.out.println("创建时间: " + createTime);
System.out.println("支付时间: " + payTime);
// 2. 查询回调状态
Map<String, Object> callbackStatus = client.getOrderApi()
.getCallbackStatus(orderNo);
int status = (int) callbackStatus.get("callback_status");
int retryCount = (int) callbackStatus.get("retry_count");
System.out.println("\n=== 回调状态 ===");
System.out.println("推送状态: " + getCallbackStatusText(status));
System.out.println("重试次数: " + retryCount);
} catch (HahaException e) {
System.err.println("查询失败: " + e.getMessage());
}
}
private String getOrderStatusText(String status) {
switch (status) {
case "paying": return "支付中";
case "paid": return "已支付";
case "refund": return "已退款";
case "closed": return "已关闭";
default: return status;
}
}
private String getCallbackStatusText(int status) {
switch (status) {
case 0: return "未推送";
case 1: return "推送成功";
case 2: return "推送失败";
default: return "未知";
}
}
}
import com.haha.sdk.HahaClient;
import com.haha.sdk.config.HahaConfig;
import com.haha.sdk.model.OpenDoorResult;
import com.haha.sdk.exception.HahaException;
import java.util.Map;
public class CompleteShoppingExample {
private HahaClient client;
public CompleteShoppingExample() {
// 初始化SDK
HahaConfig config = HahaConfig.builder()
.apiBaseUrl("http://api.hahabianli.com")
.appId("your_app_id")
.appSecret("your_app_secret")
.build();
this.client = new HahaClient(config);
}
/**
* 完整购物流程
*/
public void completeShopping(String deviceId, String userId) {
String orderNo = null;
String outTradeNo = null;
try {
// ========== 步骤1: 开门前检查 ==========
System.out.println("=== 步骤1: 开门前检查 ===");
if (!checkDeviceStatus(deviceId)) {
System.out.println("设备检查未通过,无法开门");
return;
}
// ========== 步骤2: 用户验证 ==========
System.out.println("\n=== 步骤2: 用户验证 ===");
if (!verifyUser(userId)) {
System.out.println("用户验证未通过");
return;
}
// ========== 步骤3: 开门 ==========
System.out.println("\n=== 步骤3: 开门 ===");
outTradeNo = "ORDER_" + System.currentTimeMillis();
OpenDoorResult result = client.getDeviceApi()
.openDoor(deviceId, outTradeNo, null);
orderNo = result.getOrderNo();
System.out.println("开门成功!");
System.out.println("商户订单号: " + outTradeNo);
System.out.println("哈哈订单号: " + orderNo);
// 保存订单
saveOrder(userId, deviceId, outTradeNo, orderNo);
// ========== 步骤4: 等待关门和识别 ==========
System.out.println("\n=== 步骤4: 等待用户购物 ===");
System.out.println("请用户取货并关门...");
System.out.println("(实际业务中,识别结果会通过回调通知)");
// 模拟等待
Thread.sleep(5000);
// ========== 步骤5: 处理识别结果 ==========
System.out.println("\n=== 步骤5: 处理识别结果 ===");
processRecognizeResult(orderNo);
System.out.println("\n✓ 购物流程完成");
} catch (HahaException e) {
System.err.println("业务异常: " + e.getMessage());
// 异常处理:如果已经开门,记录异常订单
if (orderNo != null) {
handleException(orderNo, e);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
// 清理资源
cleanup();
}
}
/**
* 检查设备状态
*/
private boolean checkDeviceStatus(String deviceId) throws HahaException {
// 检查在线状态
var status = client.getDeviceApi().getOnlineStatus(deviceId);
if (status.getOnlineStatus() != 1) {
System.out.println("✗ 设备离线");
return false;
}
// 检查详细状态
Map<String, Object> detailStatus = client.getDeviceApi().getDeviceStatus(deviceId);
int deviceStatus = (int) detailStatus.get("device_status");
int doorStatus = (int) detailStatus.get("door_status");
if (deviceStatus != 1) {
System.out.println("✗ 设备故障");
return false;
}
if (doorStatus == 1) {
System.out.println("✗ 设备使用中");
return false;
}
System.out.println("✓ 设备状态正常");
return true;
}
/**
* 用户验证(示例)
*/
private boolean verifyUser(String userId) {
// 实际业务中需要验证:
// 1. 用户是否签约免密支付
// 2. 用户余额是否充足
// 3. 用户是否被锁定
System.out.println("✓ 用户验证通过");
return true;
}
/**
* 保存订单到本地数据库
*/
private void saveOrder(String userId, String deviceId, String outTradeNo, String orderNo) {
System.out.println("✓ 订单已保存到数据库");
}
/**
* 处理识别结果
*/
private void processRecognizeResult(String orderNo) throws HahaException {
// 查询识别结果
Map<String, Object> result = client.getOrderApi()
.getRecognizeResult(orderNo, null);
Double totalAmount = (Double) result.get("total_amount");
Double confidence = (Double) result.get("confidence");
System.out.println("识别完成");
System.out.println("总金额: ¥" + totalAmount);
System.out.println("置信度: " + confidence);
// 判断是否需要人工审核
if (confidence < 0.8) {
System.out.println("⚠️ 置信度较低,转人工审核");
return;
}
// 扣款
System.out.println("正在扣款...");
boolean paySuccess = true; // 调用支付接口
// 通知哈哈平台
int payStatus = paySuccess ? 1 : 2;
client.getOrderApi().setPayStatus(
orderNo,
payStatus,
getCurrentTime(),
"PAY_" + System.currentTimeMillis()
);
System.out.println(paySuccess ? "✓ 支付成功" : "✗ 支付失败");
}
/**
* 异常处理
*/
private void handleException(String orderNo, Exception e) {
System.err.println("记录异常订单: " + orderNo);
// 保存到异常订单表,人工处理
}
/**
* 清理资源
*/
private void cleanup() {
// 必要时清理资源
}
private String getCurrentTime() {
return new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
.format(new java.util.Date());
}
/**
* 主函数示例
*/
public static void main(String[] args) {
CompleteShoppingExample example = new CompleteShoppingExample();
// 模拟用户购物
String deviceId = "device001";
String userId = "user123";
example.completeShopping(deviceId, userId);
}
}
import com.haha.sdk.exception.HahaException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ExceptionHandlingExample {
private static final Logger log = LoggerFactory.getLogger(ExceptionHandlingExample.class);
public void handleWithRetry(HahaClient client, String deviceId) {
int maxRetry = 3;
int retryCount = 0;
while (retryCount < maxRetry) {
try {
// 尝试开门
OpenDoorResult result = client.getDeviceApi()
.openDoor(deviceId, "ORDER_" + System.currentTimeMillis(), null);
log.info("开门成功: {}", result.getOrderNo());
break;
} catch (HahaException e) {
retryCount++;
// 根据错误码判断是否需要重试
Integer errorCode = e.getCode();
if (errorCode != null) {
switch (errorCode) {
case -3:
case -4:
// token问题,SDK会自动刷新,可以重试
log.warn("Token问题,重试第{}次", retryCount);
break;
case -101:
// 设备离线,不需要重试
log.error("设备离线,停止重试");
return;
case -103:
// 设备使用中,可以等待后重试
log.warn("设备使用中,等待5秒后重试");
try {
Thread.sleep(5000);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
}
break;
default:
log.error("开门失败: {}", e.getMessage());
return;
}
} else {
log.error("未知错误: {}", e.getMessage(), e);
return;
}
if (retryCount >= maxRetry) {
log.error("重试{}次后仍然失败", maxRetry);
}
}
}
}
}
本文档提供了哈哈零售SDK的完整使用示例,涵盖: