feat:旷世修改

This commit is contained in:
dzc committed 2025-04-11 12:47:25 +08:00
1 parent 5924d8d389
commit df96d8e847
19 files changed
+488 -98

No files matched your search

+1
View File
@@ -40,6 +40,7 @@ CREATE TABLE `third_door_log`
`api_type` tinytext NOT NULL COMMENT '请求类型',
`biz_type` tinytext NOT NULL COMMENT 'api类型',
`biz_id` varchar(2048) DEFAULT NULL COMMENT 'api类型id',
`request_id` varchar(64) DEFAULT NULL COMMENT '请求id',
`api_url` text DEFAULT NULL COMMENT 'api url',
`res` text DEFAULT NULL COMMENT 'res',
`req` text DEFAULT NULL COMMENT 'req',
@@ -39,6 +39,13 @@ public class HardSpuController {
private final HardSpuService hardSpuService;
@Operation(summary = "拉取旷世商品", description = "拉取旷世商品")
@GetMapping("/async-all")
public R asyncAll() {
hardSpuService.asyncAll();
return R.ok();
}
@Operation(summary = "根据设备id智能柜编号查询商品", description = "根据设备id智能柜编号查询商品")
@GetMapping("/get-by-cabinet-no")
public R<List<Map<Integer, List<HardSpuJoinVo>>>> getByCabinetNo(@RequestParam Long hardId, @RequestParam String cabinetNo) {
@@ -38,4 +38,9 @@ public interface HardSpuService extends IService<HardSpuEntity> {
* 根据 hardwareId 和 cabinetNo 查询商品
*/
List<Map<Integer, List<HardSpuJoinVo>>> getByCabinetNo(Long hardId, String cabinetNo);
/**
* 拉取旷世商品
*/
void asyncAll();
}
@@ -9,17 +9,17 @@ import com.bsd.pjcloud.hard.api.constant.spu.HardKsSkuTypeEnum;
import com.bsd.pjcloud.hard.api.dto.spu.HardSpuDto;
import com.bsd.pjcloud.hard.api.dto.spu.HardSpuJoinDto;
import com.bsd.pjcloud.hard.api.entity.spu.HardSpuEntity;
import com.bsd.pjcloud.hard.api.entity.spu.HardSpuJoinEntity;
import com.bsd.pjcloud.hard.api.vo.manager.HardDoorManagerVo;
import com.bsd.pjcloud.hard.api.vo.manager.HardManagerVo;
import com.bsd.pjcloud.hard.api.vo.spu.HardSpuJoinVo;
import com.bsd.pjcloud.hard.api.vo.spu.HardSpuVo;
import com.bsd.pjcloud.hard.mapper.spu.HardSpuJoinMapper;
import com.bsd.pjcloud.hard.mapper.spu.HardSpuMapper;
import com.bsd.pjcloud.hard.service.HardDoorManagerService;
import com.bsd.pjcloud.hard.service.HardManagerService;
import com.bsd.pjcloud.hard.service.HardSpuJoinService;
import com.bsd.pjcloud.hard.service.HardSpuService;
import com.bsd.pjcloud.thirdparty.api.feign.RemoterThirdKsService;
import com.bsd.pjcloud.thirdparty.dto.ks.KsBarcodeLikeDto;
import com.bsd.pjcloud.thirdparty.vo.ks.KsBarcodeLikeVo;
import com.bsd.pjcloud.wallet.api.feign.RemoteMchService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -42,6 +42,7 @@ public class HardSpuServiceImpl extends ServiceImpl<HardSpuMapper, HardSpuEntity
private final HardSpuJoinService hardSpuJoinService;
private final RemoteMchService remoteMchService;
private final RemoterThirdKsService remoterThirdKsService;
/**
@@ -125,6 +126,27 @@ public class HardSpuServiceImpl extends ServiceImpl<HardSpuMapper, HardSpuEntity
return List.of();
}
/**
* 拉取旷世商品
*/
@Override
public void asyncAll() {
int pageNum = 1;
KsBarcodeLikeDto likeDto = new KsBarcodeLikeDto();
likeDto.setPage_num(pageNum);
while (true) {
asyncAllGroup(likeDto);
break;
}
}
public void asyncAllGroup(KsBarcodeLikeDto likeDto) {
KsBarcodeLikeVo data = remoterThirdKsService.barcodeSkuLike(likeDto).getData();
if (ObjectUtil.isEmpty(data)) {
}
}
/**
* 商品是否重复
*/
@@ -0,0 +1,78 @@
package com.bsd.pjcloud.thirdparty.api.feign;
import com.bsd.pjcloud.common.core.constant.ServiceNameConstants;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.feign.annotation.NoToken;
import com.bsd.pjcloud.thirdparty.dto.ks.*;
import com.bsd.pjcloud.thirdparty.vo.ks.*;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(contextId = "remoterThirdKsService", value = ServiceNameConstants.THIRDPARTY_SERVICE)
public interface RemoterThirdKsService {
/**
* 常规SKU提交审核
*/
@NoToken
@PostMapping("/third-ks/sku-submit")
R<KsSkuSubmitVo> skuSubmit(@RequestBody KsSkuSubmitDto dto);
/**
* 集合SKU提交审核(未公开)
*/
@NoToken
@PostMapping("/third-ks/sku-submit-collection")
R<KsSkuSubmitCollectionVo> skuSubmitCollection(@RequestBody KsSkuSubmitCollectionDto dto);
/**
* SKU审核结果主动获取
*/
@NoToken
@PostMapping("/third-ks/sku-result")
R<KsSkuResultVo> skuResult(@RequestBody KsSkuResultDto dto);
/**
* SKU删除
*/
@NoToken
@PostMapping("/third-ks/sku-delete")
R<KsSkuDeleteVo> skuDelete(@RequestBody KsSkuDeleteDto dto);
/**
* 根据69码查询标准库和私有库商品信息
*/
@NoToken
@PostMapping("/third-ks/barcode-sku")
R<KsBarcodeSkuVo> barcodeSku(@RequestBody KsBarcodeSkuDto dto);
/**
* 根据ks_sku_id查询标准库和私有库商品信息
*/
@NoToken
@PostMapping("/third-ks/barcode-sku-by-id")
R<KsBarcodeSkuVo> barcodeSkuById(@RequestParam Long ksSkuId);
/**
* 模糊查询标准库和私有库商品信息
*/
@NoToken
@PostMapping("/third-ks/barcode-sku-like")
R<KsBarcodeLikeVo> barcodeSkuLike(@RequestBody KsBarcodeLikeDto dto);
/**
* SKU提交识别
*/
@NoToken
@PostMapping("/third-ks/recognition")
R<KsRecognitionVo> recognition(@RequestBody KsRecognitionDto dto);
/**
* SKU识别结果主动获取
*/
@NoToken
@PostMapping("/third-ks/recognition-result")
R<KsRecognitionResultVo> recognitionResult(@RequestBody KsRecognitionResultDto dto);
}
@@ -1,18 +1,29 @@
package com.bsd.pjcloud.thirdparty.constant.door;
import cn.hutool.core.util.ObjectUtil;
import com.bsd.pjcloud.thirdparty.constant.ThirdZyBizEnumType;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* 柜子接口
*/
@AllArgsConstructor
@Getter
public enum ThirdDoorApiTypeEnum {
DOOR_API("10", "智能柜接口"),
DISCERN_API("20", "识别接口"),
REGISTER("10", "设备注册"),
BIND("20", "设备信息绑定"),
STATUS("30", "查询设备状态"),
RESTART("40", "设备重启"),
SETTING("50", "设备设置"),
VOLUME("60", "音量设置"),
OPEN("70", "请求开锁"),
VIDEO("80", "调取另一个摄像头视频"),
OPEN_CALLBACK("90", "门锁开关通知"),
VIDEO_CALLBACK("100", "视频地址通知"),
STATUS_CALLBACK("110", "设备状态通知"),
;
private final String type;
@@ -0,0 +1,25 @@
package com.bsd.pjcloud.thirdparty.constant.door;
import cn.hutool.core.util.ObjectUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
@AllArgsConstructor
@Getter
public enum ThirdDoorBizTypeEnum {
DOOR_API("10", "智能柜接口"),
DISCERN_API("20", "识别接口"),
;
private final String type;
private final String description;
public static ThirdDoorBizTypeEnum valueOfByType(String type) {
if (ObjectUtil.isEmpty(type)) return null;
return Arrays.stream(values()).filter(v -> ObjectUtil.equals(type, v.getType())).findFirst().get();
}
}
@@ -0,0 +1,34 @@
package com.bsd.pjcloud.thirdparty.constant.door;
import cn.hutool.core.util.ObjectUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
@AllArgsConstructor
@Getter
public enum ThirdDoorKsApiTypeEnum {
REGISTER("10", "常规SKU提交审核"),
SKU_SUBMIT_COLLECTION("20", "集合SKU提交审核(未公开)"),
SKU_RESULT("30", "SKU审核结果主动获取"),
SKU_EDIT("40", "常规SKU修改"),
SKU_DELETE("50", "SKU删除"),
BARCODE_SKU("60", "根据69码查询标准库和私有库商品信息"),
BARCODE_SKU_BY_ID("70", "根据ks_sku_id查询标准库和私有库商品信息"),
BARCODE_SKU_LIKE("80", "模糊查询标准库和私有库商品信息"),
RECOGNITION("90", "SKU提交识别"),
RECOGNITION_RESULT("100", "SKU识别结果主动获取"),
;
private final String type;
private final String description;
public static ThirdDoorKsApiTypeEnum valueOfByType(String type) {
if (ObjectUtil.isEmpty(type)) return null;
return Arrays.stream(values()).filter(v -> ObjectUtil.equals(type, v.getType())).findFirst().get();
}
}
@@ -1,37 +0,0 @@
package com.bsd.pjcloud.thirdparty.constant.door;
import cn.hutool.core.util.ObjectUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* 柜子接口
*/
@AllArgsConstructor
@Getter
public enum ThordDoorApiTypeEnum {
REGISTER("10", "设备注册"),
BIND("20", "设备信息绑定"),
STATUS("30", "查询设备状态"),
RESTART("40", "设备重启"),
SETTING("50", "设备设置"),
VOLUME("60", "音量设置"),
OPEN("70", "请求开锁"),
VIDEO("80", "调取另一个摄像头视频"),
OPEN_CALLBACK("90", "门锁开关通知"),
VIDEO_CALLBACK("100", "视频地址通知"),
STATUS_CALLBACK("110", "设备状态通知"),
;
private final String type;
private final String description;
public static ThordDoorApiTypeEnum valueOfByType(String type) {
if (ObjectUtil.isEmpty(type)) return null;
return Arrays.stream(values()).filter(v -> ObjectUtil.equals(type, v.getType())).findFirst().get();
}
}
@@ -45,6 +45,12 @@ public class ThirdDoorLogEntity extends Model<ThirdDoorLogEntity> {
@Schema(description = "api类型id")
private String bizId;
/**
* 请求id
*/
@Schema(description = "请求id")
private String requestId;
/**
* api url
*/
@@ -1,3 +1,4 @@
com.bsd.pjcloud.thirdparty.api.feign.RemoterThirdKsService
com.bsd.pjcloud.thirdparty.api.feign.RemoterThirdDoorApiService
com.bsd.pjcloud.thirdparty.api.feign.RemoterThirdPartyAuthService
com.bsd.pjcloud.thirdparty.api.feign.RemoterThirdZyService
@@ -11,6 +11,8 @@ public class KsDiscernConfig {
private String baseUrl;
private String host;
private String accessKey;
private String secretKey;
@@ -16,8 +16,8 @@ import org.springframework.web.bind.annotation.*;
@RestController
@RequiredArgsConstructor
@RequestMapping("/third-door")
@Tag(description = "third-door", name = "智能柜")
@RequestMapping("/third-ks")
@Tag(description = "third-ks", name = "旷世识别")
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class ThirdKsApiController {
@@ -89,7 +89,7 @@ public class ThirdKsApiController {
@Inner
@Operation(summary = "SKU识别结果主动获取")
@PostMapping("/recognition_result")
@PostMapping("/recognition-result")
public R<KsRecognitionResultVo> recognitionResult(@RequestBody KsRecognitionResultDto dto) {
return R.ok(thirdKsApiService.recognitionResult(dto));
}
@@ -2,6 +2,7 @@ package com.bsd.pjcloud.thirdparty.service.impl.ks;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONUtil;
import com.bsd.pjcloud.thirdparty.config.KsDiscernConfig;
import com.bsd.pjcloud.thirdparty.dto.ks.*;
@@ -15,9 +16,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.*;
@Service
@@ -202,12 +201,17 @@ public class ThirdKsApiServiceImpl implements ThirdKsApiService {
public KsBarcodeLikeVo barcodeSkuLike(KsBarcodeLikeDto dto) {
long startTime = System.currentTimeMillis();
KsBaseVo ksBaseVo = new KsBaseVo();
KsApi.Api api = KsApi.BARCODE_SKU_LIKE.setBaseUrl(ksDiscernConfig.getBaseUrl()).setParams(BeanUtil.beanToMap(dto));
KsApi.Api api = KsApi.BARCODE_SKU_LIKE
.setBaseUrl(ksDiscernConfig.getBaseUrl())
.setParams(BeanUtil.beanToMap(dto))
.setAccessKey(ksDiscernConfig.getAccessKey())
.setSecretKey(ksDiscernConfig.getSecretKey())
.setHost(ksDiscernConfig.getHost());
ThirdDoorLogEntity logEntity = api.getInitLogEntity();
logEntity.setReq(JSONUtil.toJsonStr(dto));
try {
String body = JSONUtil.toJsonStr(dto);
String res = api.getHttpRequest().body(body).execute().body();
String res = api.getHttpRequest().execute().body();
if (ObjectUtil.isEmpty(res)) throw new RuntimeException("response响应为空");
logEntity.setRes(res);
ksBaseVo = JSONUtil.toBean(res, KsBaseVo.class);
@@ -4,49 +4,47 @@ package com.bsd.pjcloud.thirdparty.utils.door.api;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpRequest;
import com.bsd.pjcloud.thirdparty.constant.door.ThirdDoorApiTypeEnum;
import com.bsd.pjcloud.thirdparty.constant.door.ThordDoorApiTypeEnum;
import com.bsd.pjcloud.thirdparty.constant.door.ThirdDoorBizTypeEnum;
import com.bsd.pjcloud.thirdparty.entity.door.ThirdDoorLogEntity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Map;
public class DoorApi {
// 设备注册
public static final Api REGISTER = Api.builder().url("/ams/api/device/register").bizType(ThordDoorApiTypeEnum.REGISTER).method("post").contentType("application/json").build();
public static final Api REGISTER = Api.builder().url("/ams/api/device/register").bizType(ThirdDoorApiTypeEnum.REGISTER).method("post").contentType("application/json").build();
// 设备信息绑定
public static final Api BIND = Api.builder().url("/ams/api/device/bind").bizType(ThordDoorApiTypeEnum.BIND).method("post").contentType("application/json").build();
public static final Api BIND = Api.builder().url("/ams/api/device/bind").bizType(ThirdDoorApiTypeEnum.BIND).method("post").contentType("application/json").build();
// 查询设备状态
public static final Api STATUS = Api.builder().url("/ams/api/device/status").bizType(ThordDoorApiTypeEnum.STATUS).method("post").contentType("application/json").build();
public static final Api STATUS = Api.builder().url("/ams/api/device/status").bizType(ThirdDoorApiTypeEnum.STATUS).method("post").contentType("application/json").build();
// 设备重启
public static final Api RESTART = Api.builder().url("/ams/api/device/restart").bizType(ThordDoorApiTypeEnum.RESTART).method("post").contentType("application/json").build();
public static final Api RESTART = Api.builder().url("/ams/api/device/restart").bizType(ThirdDoorApiTypeEnum.RESTART).method("post").contentType("application/json").build();
// 设备设置
public static final Api SETTING = Api.builder().url("/ams/api/device/setting").bizType(ThordDoorApiTypeEnum.SETTING).method("post").contentType("application/json").build();
public static final Api SETTING = Api.builder().url("/ams/api/device/setting").bizType(ThirdDoorApiTypeEnum.SETTING).method("post").contentType("application/json").build();
// 音量设置
public static final Api VOLUME = Api.builder().url("/ams/api/device/volume").bizType(ThordDoorApiTypeEnum.VOLUME).method("post").contentType("application/json").build();
public static final Api VOLUME = Api.builder().url("/ams/api/device/volume").bizType(ThirdDoorApiTypeEnum.VOLUME).method("post").contentType("application/json").build();
// 请求开锁
public static final Api OPEN = Api.builder().url("/ams/api/event/open").bizType(ThordDoorApiTypeEnum.OPEN).method("post").contentType("application/json").build();
public static final Api OPEN = Api.builder().url("/ams/api/event/open").bizType(ThirdDoorApiTypeEnum.OPEN).method("post").contentType("application/json").build();
// 调取另一个摄像头视频
public static final Api VIDEO = Api.builder().url("/ams/api/event/video").bizType(ThordDoorApiTypeEnum.VIDEO).method("post").contentType("application/json").build();
public static final Api VIDEO = Api.builder().url("/ams/api/event/video").bizType(ThirdDoorApiTypeEnum.VIDEO).method("post").contentType("application/json").build();
// 门锁开关通知
public static final Api OPEN_CALLBACK = Api.builder().url("/door/callback/open").bizType(ThordDoorApiTypeEnum.OPEN_CALLBACK).method("post").contentType("application/json").build();
public static final Api OPEN_CALLBACK = Api.builder().url("/door/callback/open").bizType(ThirdDoorApiTypeEnum.OPEN_CALLBACK).method("post").contentType("application/json").build();
// 视频地址通知
public static final Api VIDEO_CALLBACK = Api.builder().url("/door/callback/video").bizType(ThordDoorApiTypeEnum.VIDEO_CALLBACK).method("post").contentType("application/json").build();
public static final Api VIDEO_CALLBACK = Api.builder().url("/door/callback/video").bizType(ThirdDoorApiTypeEnum.VIDEO_CALLBACK).method("post").contentType("application/json").build();
// 设备状态通知
public static final Api STATUS_CALLBACK = Api.builder().url("/door/callback/status").bizType(ThordDoorApiTypeEnum.STATUS_CALLBACK).method("post").contentType("application/json").build();
public static final Api STATUS_CALLBACK = Api.builder().url("/door/callback/status").bizType(ThirdDoorApiTypeEnum.STATUS_CALLBACK).method("post").contentType("application/json").build();
@Data
@Builder
@@ -62,9 +60,9 @@ public class DoorApi {
private String contentType;
private ThirdDoorApiTypeEnum apiType = ThirdDoorApiTypeEnum.DOOR_API;
private ThirdDoorBizTypeEnum apiType = ThirdDoorBizTypeEnum.DOOR_API;
private ThordDoorApiTypeEnum bizType;
private ThirdDoorApiTypeEnum bizType;
public Api setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
@@ -82,7 +80,7 @@ public class DoorApi {
}
public ThirdDoorLogEntity getInitLogEntity() {
if (ObjectUtil.isEmpty(this.apiType)) this.setApiType(ThirdDoorApiTypeEnum.DOOR_API);
if (ObjectUtil.isEmpty(this.apiType)) this.setApiType(ThirdDoorBizTypeEnum.DOOR_API);
ThirdDoorLogEntity entity = new ThirdDoorLogEntity();
entity.setBizId(null);
entity.setBizType(bizType.getType());
@@ -2,52 +2,61 @@ package com.bsd.pjcloud.thirdparty.utils.ks.api;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.http.HttpRequest;
import com.bsd.pjcloud.thirdparty.constant.door.ThirdDoorApiTypeEnum;
import com.bsd.pjcloud.thirdparty.constant.door.ThordDoorApiTypeEnum;
import com.bsd.pjcloud.thirdparty.constant.door.ThirdDoorBizTypeEnum;
import com.bsd.pjcloud.thirdparty.constant.door.ThirdDoorKsApiTypeEnum;
import com.bsd.pjcloud.thirdparty.entity.door.ThirdDoorLogEntity;
import com.bsd.pjcloud.thirdparty.utils.ks.tool.KsRetailSignUtils;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPatch;
import org.apache.http.client.methods.HttpPost;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
@Slf4j
public class KsApi {
// 常规SKU提交审核
public static final KsApi.Api SKU_SUBMIT = KsApi.Api.builder().url("/openapi/sc/v1/sku").bizType(ThordDoorApiTypeEnum.REGISTER).method("post").contentType("application/json").build();
public static final KsApi.Api SKU_SUBMIT = KsApi.Api.builder().url("/openapi/sc/v1/sku").bizType(ThirdDoorKsApiTypeEnum.REGISTER).method(HttpPost.METHOD_NAME).contentType("application/json").build();
// 集合SKU提交审核(未公开)
public static final KsApi.Api SKU_SUBMIT_COLLECTION = KsApi.Api.builder().url("/openapi/sc/v1/sku/collection").bizType(ThordDoorApiTypeEnum.REGISTER).method("post").contentType("application/json").build();
public static final KsApi.Api SKU_SUBMIT_COLLECTION = KsApi.Api.builder().url("/openapi/sc/v1/sku/collection").bizType(ThirdDoorKsApiTypeEnum.REGISTER).method(HttpPost.METHOD_NAME).contentType("application/json").build();
// SKU审核结果主动获取
public static final KsApi.Api SKU_RESULT = KsApi.Api.builder().url("/openapi/sc/v1/sku/%s").bizType(ThordDoorApiTypeEnum.REGISTER).method("post").contentType("application/json").build();
public static final KsApi.Api SKU_RESULT = KsApi.Api.builder().url("/openapi/sc/v1/sku/%s").bizType(ThirdDoorKsApiTypeEnum.REGISTER).method(HttpPost.METHOD_NAME).contentType("application/json").build();
// 常规SKU修改
public static final KsApi.Api SKU_EDIT = KsApi.Api.builder().url("/openapi/sc/v1/sku/%s").bizType(ThordDoorApiTypeEnum.REGISTER).method("patch").contentType("application/json").build();
public static final KsApi.Api SKU_EDIT = KsApi.Api.builder().url("/openapi/sc/v1/sku/%s").bizType(ThirdDoorKsApiTypeEnum.REGISTER).method(HttpPatch.METHOD_NAME).contentType("application/json").build();
// SKU删除
public static final KsApi.Api SKU_DELETE = KsApi.Api.builder().url("/openapi/sc/v1/sku/%s").bizType(ThordDoorApiTypeEnum.REGISTER).method("delete").contentType("application/json").build();
public static final KsApi.Api SKU_DELETE = KsApi.Api.builder().url("/openapi/sc/v1/sku/%s").bizType(ThirdDoorKsApiTypeEnum.REGISTER).method(HttpDelete.METHOD_NAME).contentType("application/json").build();
// 根据69码查询标准库和私有库商品信息
public static final KsApi.Api BARCODE_SKU = KsApi.Api.builder().url("/openapi/sc/v1/sku/all_sku/%s").bizType(ThordDoorApiTypeEnum.REGISTER).method("get").contentType("application/json").build();
public static final KsApi.Api BARCODE_SKU = KsApi.Api.builder().url("/openapi/sc/v1/sku/all_sku/%s").bizType(ThirdDoorKsApiTypeEnum.REGISTER).method(HttpGet.METHOD_NAME).contentType("application/json").build();
// 根据ks_sku_id查询标准库和私有库商品信息
public static final KsApi.Api BARCODE_SKU_BY_ID = KsApi.Api.builder().url("/openapi/sc/v1/sku/skus/%s").bizType(ThordDoorApiTypeEnum.REGISTER).method("get").contentType("application/json").build();
public static final KsApi.Api BARCODE_SKU_BY_ID = KsApi.Api.builder().url("/openapi/sc/v1/sku/skus/%s").bizType(ThirdDoorKsApiTypeEnum.REGISTER).method(HttpGet.METHOD_NAME).contentType("application/json").build();
// 模糊查询标准库和私有库商品信息
public static final KsApi.Api BARCODE_SKU_LIKE = KsApi.Api.builder().url("/openapi/sc/v1/sku/sku_list/%s").bizType(ThordDoorApiTypeEnum.REGISTER).method("get").contentType("application/json").build();
public static final KsApi.Api BARCODE_SKU_LIKE = KsApi.Api.builder().url("/openapi/sc/v1/sku/sku_list").bizType(ThirdDoorKsApiTypeEnum.REGISTER).method(HttpGet.METHOD_NAME).contentType("application/json").build();
// SKU提交识别
public static final KsApi.Api RECOGNITION = KsApi.Api.builder().url("/openapi/sc/v1/recognition/%s").bizType(ThordDoorApiTypeEnum.REGISTER).method("post").contentType("application/json").build();
public static final KsApi.Api RECOGNITION = KsApi.Api.builder().url("/openapi/sc/v1/recognition/%s").bizType(ThirdDoorKsApiTypeEnum.REGISTER).method(HttpPost.METHOD_NAME).contentType("application/json").build();
// SKU识别结果主动获取
public static final KsApi.Api RECOGNITION_RESULT = KsApi.Api.builder().url("/openapi/sc/v1/recognition/%s").bizType(ThordDoorApiTypeEnum.REGISTER).method("post").contentType("application/json").build();
public static final KsApi.Api RECOGNITION_RESULT = KsApi.Api.builder().url("/openapi/sc/v1/recognition/%s").bizType(ThirdDoorKsApiTypeEnum.REGISTER).method(HttpPost.METHOD_NAME).contentType("application/json").build();
@Data
@Builder
@@ -58,15 +67,26 @@ public class KsApi {
private String url;
private Map<String, Object> params;
private Map<String, Object> params = new TreeMap<>();
private String body;
private String method;
private String contentType;
private ThirdDoorApiTypeEnum apiType = ThirdDoorApiTypeEnum.DISCERN_API;
private ThirdDoorBizTypeEnum apiType = ThirdDoorBizTypeEnum.DISCERN_API;
private ThordDoorApiTypeEnum bizType;
private ThirdDoorKsApiTypeEnum bizType;
private String accessKey;
private String secretKey;
private String host = "";
private String requestId;
public KsApi.Api setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
@@ -78,35 +98,89 @@ public class KsApi {
return this;
}
public HttpRequest getHttpRequest() {
String fullPatch = baseUrl + url;
if (ObjectUtil.isNotEmpty(params)) {
StringBuilder query = new StringBuilder();
for (Map.Entry<String, Object> entry : params.entrySet()) {
public KsApi.Api setAccessKey(String accessKey) {
this.accessKey = accessKey;
return this;
}
public KsApi.Api setSecretKey(String secretKey) {
this.secretKey = secretKey;
return this;
}
public KsApi.Api setHost(String host) {
this.host = host;
return this;
}
/**
* 获取当前时间戳
*/
public Long getXRequestDate() {
return System.currentTimeMillis();
}
public String getQueryString() {
if (ObjectUtil.isEmpty(params)) return null;
StringBuilder query = new StringBuilder();
for (Map.Entry<String, Object> entry : params.entrySet()) {
if (ObjectUtil.isNotEmpty(query)) query.append("&");
if (ObjectUtil.isNotEmpty(entry.getValue())) {
query.append(URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8)).append("=").append(URLEncoder.encode(String.valueOf(entry.getValue()), StandardCharsets.UTF_8));
}
}
return query.toString();
}
/**
* 获取header
*/
public Map<String, List<String>> getHeader() {
// 初始化数据
if (ObjectUtil.isEmpty(getBody())) setBody("");
if (ObjectUtil.isEmpty(getParams())) setParams(new TreeMap<>());
// 计算签名
Long currentTime = getXRequestDate();
String queryString = getQueryString();
String auth = KsRetailSignUtils.getSignAuth(getHost(), getUrl(), contentType, getMethod(), currentTime, getAccessKey(), getSecretKey(), getBody(), queryString);
String requestId = getXRequestDate() + RandomUtil.randomString(19);
setRequestId(requestId);
Map<String, List<String>> header = new HashMap<>();
header.put("Authorization", List.of(auth));
header.put("Content-Type", List.of(getContentType()));
header.put("X-Request-Date", List.of(String.valueOf(getXRequestDate())));
header.put("X-Request-id", List.of(requestId));
header.put("Referer", List.of("https://" + getHost()));
return header;
}
public HttpRequest getHttpRequest() {
String fullPatch = baseUrl + url;
String query = getQueryString();
if (ObjectUtil.isNotEmpty(query)) {
fullPatch = fullPatch + "?" + query;
}
if (ObjectUtil.equals(method, "post")) {
return HttpRequest.post(fullPatch).contentType(contentType);
} else if (ObjectUtil.equals(method, "get")) {
return HttpRequest.get(fullPatch).contentType(contentType);
} else if (ObjectUtil.equals(method, "patch")) {
return HttpRequest.patch(fullPatch).contentType(contentType);
} else if (ObjectUtil.equals(method, "delete")) {
return HttpRequest.delete(fullPatch).contentType(contentType);
if (ObjectUtil.equals(method, HttpPost.METHOD_NAME)) {
return HttpRequest.post(fullPatch).header(getHeader()).body(getBody());
} else if (ObjectUtil.equals(method, HttpGet.METHOD_NAME)) {
return HttpRequest.get(fullPatch).header(getHeader());
} else if (ObjectUtil.equals(method, HttpPatch.METHOD_NAME)) {
return HttpRequest.patch(fullPatch).header(getHeader()).body(getBody());
} else if (ObjectUtil.equals(method, HttpDelete.METHOD_NAME)) {
return HttpRequest.delete(fullPatch).header(getHeader()).body(getBody());
} else {
return null;
}
}
public ThirdDoorLogEntity getInitLogEntity() {
if (ObjectUtil.isEmpty(this.apiType)) this.setApiType(ThirdDoorApiTypeEnum.DISCERN_API);
if (ObjectUtil.isEmpty(this.apiType)) this.setApiType(ThirdDoorBizTypeEnum.DISCERN_API);
ThirdDoorLogEntity entity = new ThirdDoorLogEntity();
entity.setBizId(null);
entity.setBizType(bizType.getType());
entity.setApiType(apiType.getType());
entity.setApiUrl(url);
entity.setRequestId(getRequestId());
return entity;
}
@@ -0,0 +1,101 @@
package com.bsd.pjcloud.thirdparty.utils.ks.tool;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class KsMD5Encryption {
private final static String[] hexArray = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};
/***
* 对指定的字符串进行MD5加密
*/
public static String encrypByMD5(String originString) {
try {
//创建具有MD5算法的信息摘要
MessageDigest md = MessageDigest.getInstance("MD5");
//使用指定的字节数组对摘要进行最后更新,然后完成摘要计算
byte[] bytes = md.digest(originString.getBytes());
//将得到的字节数组变成字符串返回
String s = byteArrayToHex(bytes);
return s.toUpperCase();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
/**
* 使用 HMAC-SHA1 签名方法对对encryptText进行签名
*
* @param encryptText 被签名的字符串
* @param encryptKey 密钥
* @return
* @throws Exception
*/
public static String encrypByHMACSHA1(String encryptText, String encryptKey) {
try {
byte[] data = encryptKey.getBytes(StandardCharsets.UTF_8);
//根据给定的字节数组构造一个密钥,第二参数指定一个密钥算法的名称
SecretKey secretKey = new SecretKeySpec(data, "HmacSHA1");
//生成一个指定 Mac 算法 的 Mac 对象
Mac mac = Mac.getInstance("HmacSHA1");
//用给定密钥初始化 Mac 对象
mac.init(secretKey);
byte[] text = encryptText.getBytes(StandardCharsets.UTF_8);
//完成 Mac 操作
String s = byteArrayToHex(mac.doFinal(text));
return s;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/***
* 对指定的字符串进行MD5加密
*/
public static String encrypBySHA1(String originString) {
try {
//创建具有MD5算法的信息摘要
MessageDigest md = MessageDigest.getInstance("SHA1");
//使用指定的字节数组对摘要进行最后更新,然后完成摘要计算
byte[] bytes = md.digest(originString.getBytes());
//将得到的字节数组变成字符串返回
String s = byteArrayToHex(bytes);
return s.toUpperCase();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
/**
* 将字节数组转换成十六进制,并以字符串的形式返回
* 128位是指二进制位。二进制太长,所以一般都改写成16进制,
* 每一位16进制数可以代替4位二进制数,所以128位二进制数写成16进制就变成了128/4=32位。
*/
public static String byteArrayToHex(byte[] b) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < b.length; i++) {
sb.append(byteToHex(b[i]));
}
return sb.toString();
}
/**
* 将一个字节转换成十六进制,并以字符串的形式返回
*/
public static String byteToHex(byte b) {
int n = b;
if (n < 0)
n = n + 256;
int d1 = n / 16;
int d2 = n % 16;
return hexArray[d1] + hexArray[d2];
}
}
@@ -0,0 +1,56 @@
package com.bsd.pjcloud.thirdparty.utils.ks.tool;
import lombok.extern.slf4j.Slf4j;
import java.nio.charset.StandardCharsets;
@Slf4j
public class KsRetailSignUtils {
private static final String ALGORITHM = "HMAC-SHA1";
public static String getSignAuth(String host, String uri, String contentType, String methodType, long timeMillis, String ak, String sk, String body, String queryString) {
log.info("host={}, uri={}, contentType={}, methodType={}, timeMillis={}, ak={}, sk={}, body={}, queryString={}", host, uri, contentType, methodType, timeMillis, ak, sk, body, queryString);
String signedHeaders = getSignedHeaders(host, contentType, timeMillis);
log.info("signedHeaders = {}", signedHeaders);
String payloadHex = getMD5Hex(body);
log.info("payloadHex = {}", payloadHex);
String request = getRequest(methodType, uri, queryString, signedHeaders, payloadHex);
log.info("request = {}", request);
String requextHex = getSHA1Hex(request);
log.info("requextHex = {}", requextHex);
String stringToSign = getStringToSign(ALGORITHM, requextHex);
log.info("stringToSign = {}", stringToSign);
String signature = getSignature(stringToSign, sk);
log.info("signature = {}", signature);
String auth = KsMD5Encryption.encrypByHMACSHA1(stringToSign, sk);
log.info("auth = {}", auth);
return String.format("%s %s:%s", ALGORITHM, ak, signature);
}
private static String getSignedHeaders(String host, String contentType, long time) {
return host.toLowerCase() + ";" + contentType.toLowerCase() + ";" + String.valueOf(time).toLowerCase();
}
private static String getMD5Hex(String payload) {
String payloadUtf8 = new String(payload.getBytes(), StandardCharsets.UTF_8);
return KsMD5Encryption.encrypByMD5(payloadUtf8).toLowerCase();
}
private static String getSHA1Hex(String request) {
String requestUtf8 = new String(request.getBytes(), StandardCharsets.UTF_8);
return KsMD5Encryption.encrypBySHA1(requestUtf8).toLowerCase();
}
private static String getRequest(String httpRequestMethod, String uri, String queryString, String signHeaders, String hex) {
return httpRequestMethod + "\n" + uri + "\n" + queryString + "\n" + signHeaders + "\n" + hex;
}
private static String getStringToSign(String algorithm, String requextHex) {
return algorithm + "\n" + requextHex;
}
private static String getSignature(String stringToSign, String sk) {
return KsMD5Encryption.encrypByHMACSHA1(stringToSign, sk);
}
}
@@ -80,9 +80,11 @@ door:
# 旷世识别
ks-discern:
base-url: https://gwycport.zj.gov.cn
base-url: https://retail.xlsdn.com
access-key: ed5A923eF0e941A1968eGTpF
secret-key: Ex3X0kgoc94sBOtivjWm5Vz9AyZTOUpl
host: retail.xlsdn.com