this is 4.22 update

This commit is contained in:
chen-xin-zhi 2025-05-03 11:55:10 +08:00
parent 8837d8bc54
commit 4ebe4839fb
9 changed files with 440 additions and 7 deletions

View File

@ -1,6 +1,8 @@
package com.cultural.heritage.controller.clothes;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
@ -17,24 +19,31 @@ import com.cultural.heritage.model.dto.CommonRequest;
import com.cultural.heritage.model.dto.clothes.ClothesAddRequest;
import com.cultural.heritage.model.dto.clothes.ClothesQueryRequest;
import com.cultural.heritage.model.dto.clothes.ClothesUpdateRequest;
import com.cultural.heritage.model.dto.facelift.ClothesUrlObj;
import com.cultural.heritage.model.dto.facelift.GarmentObj;
import com.cultural.heritage.model.dto.facelift.LogoUrlObj;
import com.cultural.heritage.model.dto.facelift.ModelObj;
import com.cultural.heritage.model.entity.Clothes;
import com.cultural.heritage.model.vo.clothes.ClothesLabelVO;
import com.cultural.heritage.model.vo.clothes.ClothesVO;
import com.cultural.heritage.service.clothes.ClothesService;
import com.cultural.heritage.service.common.CommonService;
import com.cultural.heritage.utils.DecoderUtils;
import com.cultural.heritage.utils.Sign;
import com.google.gson.Gson;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@RestController
@ -292,6 +301,47 @@ public class ClothesController {
/**
* 小程序端用户调用换装api
* @param modelURL 模特Url
* @param clothesURL 服装URL
* @return
*/
@PostMapping("/facelift")
@Operation(summary = "小程序端用户调用换装api", description = "参数服装id权限管理员(admin, boss)方法名updateClothesShelvesStatus")
@AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
public BaseResponse<String> invokeChangeClothesApi(@RequestParam String modelURL, @RequestParam String clothesURL) {
if (StringUtils.isBlank(modelURL) || StringUtils.isBlank(clothesURL)) {
throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数不能为空");
}
Map<String, Object> param = new HashMap<>();
param.put("req_key", "dressing_diffusion");
ModelObj modelObj = ModelObj.builder().id("1").url(modelURL).build();
param.put("model", modelObj);
ClothesUrlObj clothesUrlObj = ClothesUrlObj.builder().url(clothesURL).build();
List<ClothesUrlObj> clothesUrlObjList = new ArrayList<>();
clothesUrlObjList.add(clothesUrlObj);
GarmentObj garmentObj = GarmentObj.builder().id("1").data(clothesUrlObjList).build();
param.put("garment", garmentObj);
param.put("return_url", true);
LogoUrlObj logoUrlObj = LogoUrlObj.builder().add_logo(false).position(0).language(0).logo_text_content("这里是明水印内容").build();
param.put("logo_url", logoUrlObj);
// 使用 Gson Map 转换为 byte[]
Gson gson = new Gson();
byte[] body = gson.toJson(param).getBytes(StandardCharsets.UTF_8);
String responseBody = null;
try {
responseBody = Sign.invokeChangeClothesApi(body);
} catch (Exception e) {
e.printStackTrace();
}
// 使用 fastjson responseBody 字符串解析为 JSONObject
JSONObject jsonObject = JSONObject.parseObject(responseBody);
// JSON 中获取 "data" 对象然后获取 "image_urls" 数组
JSONArray imageUrls = jsonObject.getJSONObject("data").getJSONArray("image_urls");
return ResultUtils.success(imageUrls.getString(0));
}

View File

@ -0,0 +1,24 @@
package com.cultural.heritage.model.dto.facelift;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ClothesUrlObj implements Serializable {
/**
* 服装url
*/
private String url;
@Serial
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,31 @@
package com.cultural.heritage.model.dto.facelift;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class GarmentObj implements Serializable {
/**
* 模特配置
*/
private String id;
/**
* 服装URL列表
*/
private List<ClothesUrlObj> data;
@Serial
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,39 @@
package com.cultural.heritage.model.dto.facelift;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class LogoUrlObj implements Serializable {
/**
* 是否添加水印
*/
private Boolean add_logo;
/**
* 水印位置
*/
private Integer position;
/**
* 水印的语言
*/
private Integer language;
/**
* 水印的内容
*/
private String logo_text_content;
@Serial
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,31 @@
package com.cultural.heritage.model.dto.facelift;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ModelObj implements Serializable {
/**
* 模特配置
*/
private String id;
/**
* 模特URL
*/
private String url;
@Serial
private static final long serialVersionUID = 4460640673274461809L;
}

View File

@ -0,0 +1,258 @@
package com.cultural.heritage.utils;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* Copyright (year) Beijing Volcano Engine Technology Ltd.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
public class Sign {
private static final BitSet URLENCODER = new BitSet(256);
private static final String CONST_ENCODE = "0123456789ABCDEF";
public static final Charset UTF_8 = StandardCharsets.UTF_8;
private final String region;
private final String service;
private final String schema;
private final String host;
private final String path;
private final String ak;
private final String sk;
static {
int i;
for (i = 97; i <= 122; ++i) {
URLENCODER.set(i);
}
for (i = 65; i <= 90; ++i) {
URLENCODER.set(i);
}
for (i = 48; i <= 57; ++i) {
URLENCODER.set(i);
}
URLENCODER.set('-');
URLENCODER.set('_');
URLENCODER.set('.');
URLENCODER.set('~');
}
public Sign(String region, String service, String schema, String host, String path, String ak, String sk) {
this.region = region;
this.service = service;
this.host = host;
this.schema = schema;
this.path = path;
this.ak = ak;
this.sk = sk;
}
// public static void main(String[] args) throws Exception {
// String SecretAccessKey = "T0dJeU1HVTRaamsxWldSaE5HTTNOemswWVdRMk1qUmxaVEprWXpFNFpUYw==";
// String AccessKeyID = "AKLTNzZjODdkZGQ5YjkwNDhlZmFlNDFkNWQ1ODM4YmI4NmU";
// // 请求地址
// String endpoint = "visual.volcengineapi.com";
// String path = "/"; // 路径不包含 Query// 请求接口信息
// String service = "cv";
// String region = "cn-north-1";
// String schema = "https";
// Sign sign = new Sign(region, service, schema, endpoint, path, AccessKeyID, SecretAccessKey);
//
// String action = "CVProcess";
// String version = "2022-08-31";
//
// Date date = new Date();
// HashMap<String, String> queryMap = new HashMap<>() {{
// put("Limit", "1");
// }};
//
// sign.doRequest("POST", queryMap, null, date, action, version);
// }
public static String invokeChangeClothesApi(byte[] body) throws Exception {
String SecretAccessKey = "T0dJeU1HVTRaamsxWldSaE5HTTNOemswWVdRMk1qUmxaVEprWXpFNFpUYw==";
String AccessKeyID = "AKLTNzZjODdkZGQ5YjkwNDhlZmFlNDFkNWQ1ODM4YmI4NmU";
// 请求地址
String endpoint = "visual.volcengineapi.com";
String path = "/"; // 路径不包含 Query// 请求接口信息
String service = "cv";
String region = "cn-north-1";
String schema = "https";
Sign sign = new Sign(region, service, schema, endpoint, path, AccessKeyID, SecretAccessKey);
String action = "CVProcess";
String version = "2022-08-31";
Date date = new Date();
HashMap<String, String> queryMap = new HashMap<>() {{
put("Limit", "1");
}};
return sign.doRequest("POST", queryMap, body, date, action, version);
}
public String doRequest(String method, Map<String, String> queryList, byte[] body,
Date date, String action, String version) throws Exception {
if (body == null) {
body = new byte[0];
}
String xContentSha256 = hashSHA256(body);
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
String xDate = sdf.format(date);
String shortXDate = xDate.substring(0, 8);
String contentType = "application/json";
String signHeader = "host;x-date;x-content-sha256;content-type";
SortedMap<String, String> realQueryList = new TreeMap<>(queryList);
realQueryList.put("Action", action);
realQueryList.put("Version", version);
StringBuilder querySB = new StringBuilder();
for (String key : realQueryList.keySet()) {
querySB.append(signStringEncoder(key)).append("=").append(signStringEncoder(realQueryList.get(key))).append("&");
}
querySB.deleteCharAt(querySB.length() - 1);
String canonicalStringBuilder = method + "\n" + path + "\n" + querySB + "\n" +
"host:" + host + "\n" +
"x-date:" + xDate + "\n" +
"x-content-sha256:" + xContentSha256 + "\n" +
"content-type:" + contentType + "\n" +
"\n" +
signHeader + "\n" +
xContentSha256;
System.out.println(canonicalStringBuilder);
String hashcanonicalString = hashSHA256(canonicalStringBuilder.getBytes());
String credentialScope = shortXDate + "/" + region + "/" + service + "/request";
String signString = "HMAC-SHA256" + "\n" + xDate + "\n" + credentialScope + "\n" + hashcanonicalString;
byte[] signKey = genSigningSecretKeyV4(sk, shortXDate, region, service);
String signature = HexFormat.of().formatHex(hmacSHA256(signKey, signString));
URL url = new URL(schema + "://" + host + path + "?" + querySB);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod(method);
conn.setRequestProperty("Host", host);
conn.setRequestProperty("X-Date", xDate);
conn.setRequestProperty("X-Content-Sha256", xContentSha256);
conn.setRequestProperty("Content-Type", contentType);
conn.setRequestProperty("Authorization", "HMAC-SHA256" +
" Credential=" + ak + "/" + credentialScope +
", SignedHeaders=" + signHeader +
", Signature=" + signature);
if (!Objects.equals(conn.getRequestMethod(), "GET")) {
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
os.write(body);
os.flush();
os.close();
}
conn.connect();
int responseCode = conn.getResponseCode();
InputStream is;
if (responseCode == 200) {
is = conn.getInputStream();
} else {
is = conn.getErrorStream();
}
String responseBody = new String(is.readAllBytes());
is.close();
System.out.println(responseCode);
System.out.println(responseBody);
return responseBody;
}
private String signStringEncoder(String source) {
if (source == null) {
return null;
}
StringBuilder buf = new StringBuilder(source.length());
ByteBuffer bb = UTF_8.encode(source);
while (bb.hasRemaining()) {
int b = bb.get() & 255;
if (URLENCODER.get(b)) {
buf.append((char) b);
} else if (b == 32) {
buf.append("%20");
} else {
buf.append("%");
char hex1 = CONST_ENCODE.charAt(b >> 4);
char hex2 = CONST_ENCODE.charAt(b & 15);
buf.append(hex1);
buf.append(hex2);
}
}
return buf.toString();
}
public static String hashSHA256(byte[] content) throws Exception {
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
return HexFormat.of().formatHex(md.digest(content));
} catch (Exception e) {
throw new Exception(
"Unable to compute hash while signing request: "
+ e.getMessage(), e);
}
}
public static byte[] hmacSHA256(byte[] key, String content) throws Exception {
try {
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(key, "HmacSHA256"));
return mac.doFinal(content.getBytes());
} catch (Exception e) {
throw new Exception(
"Unable to calculate a request signature: "
+ e.getMessage(), e);
}
}
private byte[] genSigningSecretKeyV4(String secretKey, String date, String region, String service) throws Exception {
byte[] kDate = hmacSHA256((secretKey).getBytes(), date);
byte[] kRegion = hmacSHA256(kDate, region);
byte[] kService = hmacSHA256(kRegion, service);
return hmacSHA256(kService, "request");
}
}

View File

@ -47,7 +47,7 @@ server:
session:
cookie:
max-age: 2592000
timeout: 720h
timeout: 2592000
mybatis-plus:
mapper-locations: classpath:mapper/*.xml

View File

@ -52,7 +52,7 @@ server:
session:
cookie:
max-age: 2592000
timeout: 720h
timeout: 2592000
mybatis-plus:
mapper-locations: classpath:mapper/*.xml

View File

@ -1,6 +1,6 @@
spring:
profiles:
active: prod
active: dev