|
|
@ -19,6 +19,7 @@ import org.jeecg.api.bean.PageBean; |
|
|
|
import org.jeecg.api.bean.WxQrCodeVo; |
|
|
|
import org.jeecg.api.service.AppletIndexService; |
|
|
|
import org.jeecg.common.api.vo.Result; |
|
|
|
import org.jeecg.common.util.RedisUtil; |
|
|
|
import org.jeecg.config.shiro.ShiroRealm; |
|
|
|
import org.jeecg.modules.commonAddress.entity.CommonAddress; |
|
|
|
import org.jeecg.modules.commonAddress.service.ICommonAddressService; |
|
|
@ -89,6 +90,7 @@ import java.awt.image.BufferedImage; |
|
|
|
import java.io.*; |
|
|
|
import java.math.BigDecimal; |
|
|
|
import java.net.URL; |
|
|
|
import java.nio.file.Files; |
|
|
|
import java.time.LocalDateTime; |
|
|
|
import java.time.ZoneId; |
|
|
|
import java.time.temporal.ChronoUnit; |
|
|
@ -162,6 +164,8 @@ public class AppletIndexServiceImpl implements AppletIndexService { |
|
|
|
@Autowired |
|
|
|
private ICommonordergiveService commonordergiveService; |
|
|
|
|
|
|
|
@Autowired |
|
|
|
private RedisUtil redisUtil; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -1107,54 +1111,18 @@ public class AppletIndexServiceImpl implements AppletIndexService { |
|
|
|
ResponseEntity<byte[]> entity = rest.exchange(url, HttpMethod.POST, requestEntity, byte[].class, new Object[0]); |
|
|
|
byte[] result = entity.getBody(); |
|
|
|
|
|
|
|
inputStream = new ByteArrayInputStream(result); |
|
|
|
String tempSave = codeImg; |
|
|
|
String filePath = tempSave; |
|
|
|
|
|
|
|
file = new File(filePath); |
|
|
|
if (!file.exists()) { |
|
|
|
file.createNewFile(); |
|
|
|
} |
|
|
|
outputStream = new FileOutputStream(file); |
|
|
|
int len = 0; |
|
|
|
byte[] buf = new byte[1024]; |
|
|
|
while ((len = inputStream.read(buf, 0, 1024)) != -1) { |
|
|
|
outputStream.write(buf, 0, len); |
|
|
|
} |
|
|
|
outputStream.flush(); |
|
|
|
/** |
|
|
|
* 将文件上传至阿里云 |
|
|
|
*/ |
|
|
|
DiskFileItemFactory factory = new DiskFileItemFactory(16, null); |
|
|
|
FileItem item = factory.createItem("File", "text/plain", true, file.getName()); |
|
|
|
int bytesRead = 0; |
|
|
|
byte[] buffer = new byte[8192]; |
|
|
|
try { |
|
|
|
FileInputStream fis = new FileInputStream(file); |
|
|
|
OutputStream os = item.getOutputStream(); |
|
|
|
while ((bytesRead = fis.read(buffer, 0, 8192)) != -1) { |
|
|
|
os.write(buffer, 0, bytesRead); |
|
|
|
} |
|
|
|
os.close(); |
|
|
|
fis.close(); |
|
|
|
} catch (IOException e) { |
|
|
|
e.printStackTrace(); |
|
|
|
} |
|
|
|
MultipartFile mf = new CommonsMultipartFile(item); |
|
|
|
//返回图片下载地址 |
|
|
|
WxQrCodeVo wxCodeVo = new WxQrCodeVo(); |
|
|
|
this.uploadAliYunOss(mf); |
|
|
|
|
|
|
|
|
|
|
|
CommonConfig image_go_url = commonConfigService.lambdaQuery() |
|
|
|
.eq(CommonConfig::getKeyName, "image_go_url") |
|
|
|
.one(); |
|
|
|
|
|
|
|
String qrCodeImageUrl = image_go_url.getKeyContent()+this.uploadAliYunOss(mf); |
|
|
|
String qrCodeImageUrl = image_go_url.getKeyContent()+ this.uploadAliYunOss(result, file.getName()); |
|
|
|
String backgroundImageUrl = qr_code.getKeyContent(); |
|
|
|
String outputFilePath = "combined_image_code"; |
|
|
|
String s = this.generateAndCombineImagesFromUrl(qrCodeImageUrl, backgroundImageUrl, outputFilePath); |
|
|
|
wxCodeVo.setUrl(s); |
|
|
|
// String s = this.generateAndCombineImagesFromUrl2(qrCodeImageUrl, backgroundImageUrl, outputFilePath); |
|
|
|
wxCodeVo.setUrl(null); |
|
|
|
wxCodeVo.setName("陌美人珠宝欢迎您"); |
|
|
|
|
|
|
|
|
|
|
@ -1187,84 +1155,152 @@ public class AppletIndexServiceImpl implements AppletIndexService { |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
//获取推广二维码 2 |
|
|
|
@Override |
|
|
|
public byte[] getInviteCode2(String token){ |
|
|
|
HanHaiMember member = shiroRealm.checkUserTokenIsEffectHanHaiOpenId(token); |
|
|
|
|
|
|
|
// 获取环境配置 |
|
|
|
CommonConfig vsion = commonConfigService.lambdaQuery() |
|
|
|
.eq(CommonConfig::getKeyName, "v_sion") |
|
|
|
.one(); |
|
|
|
Integer vsionStr = Integer.parseInt(vsion.getKeyContent()); |
|
|
|
String trial = "release"; |
|
|
|
if(vsionStr == 0){ |
|
|
|
trial= "release"; |
|
|
|
}else if(vsionStr == 1){ |
|
|
|
trial= "trial"; |
|
|
|
}else{ |
|
|
|
trial= "develop"; |
|
|
|
} |
|
|
|
|
|
|
|
// 获取必要的配置信息 |
|
|
|
CommonConfig xcxSharePage = commonConfigService.lambdaQuery() |
|
|
|
.eq(CommonConfig::getKeyName, "xcxSharePage") |
|
|
|
.one(); |
|
|
|
|
|
|
|
CommonConfig oneImage = commonConfigService.lambdaQuery() |
|
|
|
.eq(CommonConfig::getKeyName, "codeImg") |
|
|
|
.one(); |
|
|
|
|
|
|
|
CommonConfig qr_code = commonConfigService.lambdaQuery() |
|
|
|
.eq(CommonConfig::getKeyName, "qr_code") |
|
|
|
.one(); |
|
|
|
|
|
|
|
CommonConfig image_go_url = commonConfigService.lambdaQuery() |
|
|
|
.eq(CommonConfig::getKeyName, "image_go_url") |
|
|
|
.one(); |
|
|
|
|
|
|
|
String backgroundImageUrl = qr_code.getKeyContent(); |
|
|
|
|
|
|
|
// 尝试从缓存获取二维码 |
|
|
|
String cacheKey = "CodeImage::" + trial + member.getId(); |
|
|
|
WxQrCodeVo wxCodeVo = new WxQrCodeVo(); |
|
|
|
|
|
|
|
wxCodeVo.setName("陌美人珠宝欢迎您"); |
|
|
|
|
|
|
|
// 如果启用了Redis缓存,可以取消下面注释 |
|
|
|
// String cachedQrCode = (String) redisUtil.get(cacheKey); |
|
|
|
// if(cachedQrCode != null){ |
|
|
|
// String combinedImageUrl = this.generateAndCombineImagesFromUrl(cachedQrCode, backgroundImageUrl, "combined_image_code"); |
|
|
|
// wxCodeVo.setUrl(combinedImageUrl); |
|
|
|
// return Result.OK(wxCodeVo); |
|
|
|
// } |
|
|
|
|
|
|
|
public String generateAndCombineImagesFromUrl(String qrCodeImageUrl, String backgroundUrl, String outputFilePath) { |
|
|
|
try { |
|
|
|
|
|
|
|
// 准备微信API请求参数 |
|
|
|
String key = "shareId=" + member.getId(); |
|
|
|
Map<String, Object> param = new HashMap<>(); |
|
|
|
param.put("path", xcxSharePage.getKeyContent() + "?" + key); |
|
|
|
param.put("scene", member.getId()); |
|
|
|
param.put("width", 150); |
|
|
|
param.put("auto_color", false); |
|
|
|
param.put("env_version", trial); |
|
|
|
|
|
|
|
// Map<String, Object> line_color = new HashMap<>(); |
|
|
|
// line_color.put("r", 0); |
|
|
|
// line_color.put("g", 0); |
|
|
|
// line_color.put("b", 0); |
|
|
|
// param.put("line_color", line_color); |
|
|
|
|
|
|
|
|
|
|
|
param.put("is_hyaline", true); |
|
|
|
|
|
|
|
// 获取微信小程序码 |
|
|
|
String accessToken = this.getAccessToken(); |
|
|
|
String url = "https://api.weixin.qq.com/wxa/getwxacode?access_token=" + accessToken; |
|
|
|
|
|
|
|
// 请求微信API获取二维码图片数据 |
|
|
|
RestTemplate rest = new RestTemplate(); |
|
|
|
MultiValueMap<String, String> headers = new LinkedMultiValueMap<>(); |
|
|
|
org.springframework.http.HttpEntity requestEntity = new org.springframework.http.HttpEntity(JSON.toJSONString(param), headers); |
|
|
|
ResponseEntity<byte[]> entity = rest.exchange(url, HttpMethod.POST, requestEntity, byte[].class, new Object[0]); |
|
|
|
byte[] qrCodeBytes = entity.getBody(); |
|
|
|
|
|
|
|
// 直接将二维码图片转为MultipartFile,避免写入临时文件 |
|
|
|
// MultipartFile qrCodeFile = createMultipartFile(qrCodeBytes, "qrcode.jpg"); |
|
|
|
|
|
|
|
// 上传二维码到阿里云并获取URL |
|
|
|
// String qrCodeImageUrl = image_go_url.getKeyContent() + this.uploadAliYunOss(qrCodeFile); |
|
|
|
|
|
|
|
// 合并图片并上传 |
|
|
|
// String combinedImageUrl = this.generateAndCombineImagesFromUrl2(qrCodeBytes, backgroundImageUrl); |
|
|
|
|
|
|
|
// 设置返回数据 |
|
|
|
|
|
|
|
// 如果启用了Redis缓存,可以取消下面注释 |
|
|
|
//redisUtil.set(cacheKey, qrCodeImageUrl, 3600); // 缓存一小时 |
|
|
|
|
|
|
|
return this.generateAndCombineImagesFromUrl2(qrCodeBytes, backgroundImageUrl); |
|
|
|
} catch (Exception e) { |
|
|
|
e.printStackTrace(); |
|
|
|
|
|
|
|
return null; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public byte[] generateAndCombineImagesFromUrl2(byte[] qrCodeImageByte, String backgroundUrl) { |
|
|
|
File file = null; |
|
|
|
try { |
|
|
|
// 从URL加载小程序码图像 |
|
|
|
URL qrCodeUrl = new URL(qrCodeImageUrl); |
|
|
|
BufferedImage qrCodeImage = ImageIO.read(qrCodeUrl); |
|
|
|
// 从字节数组加载小程序码图像 |
|
|
|
BufferedImage qrCodeImage = ImageIO.read(new ByteArrayInputStream(qrCodeImageByte)); |
|
|
|
|
|
|
|
// 从URL加载背景图像 |
|
|
|
URL backgroundImageUrl = new URL(backgroundUrl); |
|
|
|
BufferedImage backgroundImage = ImageIO.read(backgroundImageUrl); |
|
|
|
|
|
|
|
// 创建一个新的BufferedImage来保存合并后的图像 |
|
|
|
BufferedImage combinedImage = new BufferedImage(backgroundImage.getWidth(), backgroundImage.getHeight(), BufferedImage.TYPE_INT_ARGB); |
|
|
|
Graphics2D g2d = combinedImage.createGraphics(); |
|
|
|
Graphics2D g2d = backgroundImage.createGraphics(); |
|
|
|
|
|
|
|
// 绘制背景图像 |
|
|
|
g2d.drawImage(backgroundImage, 0, 0, null); |
|
|
|
int wh = backgroundImage.getWidth() / 3; |
|
|
|
|
|
|
|
// 计算小程序码放置的位置(这里以中心位置为例) |
|
|
|
int qrCodeX = (backgroundImage.getWidth() - qrCodeImage.getWidth()) / 2; |
|
|
|
int qrCodeY = (backgroundImage.getHeight() - qrCodeImage.getHeight()) / 2; |
|
|
|
// |
|
|
|
// int backgroundHeight = backgroundImage.getHeight(); |
|
|
|
// int qrCodeHeight = qrCodeImage.getHeight(); |
|
|
|
// int qrCodeY = (int) (backgroundHeight - qrCodeHeight / 2); |
|
|
|
int qrCodeX = (backgroundImage.getWidth() - wh) / 2; |
|
|
|
int qrCodeY = (int) ((backgroundImage.getHeight() - wh) * 0.6); |
|
|
|
|
|
|
|
// 绘制小程序码图像 |
|
|
|
g2d.drawImage(qrCodeImage, qrCodeX, 1100, null); |
|
|
|
g2d.drawImage(qrCodeImage, qrCodeX, qrCodeY, wh, wh, null); |
|
|
|
|
|
|
|
// 释放Graphics2D资源 |
|
|
|
g2d.dispose(); |
|
|
|
|
|
|
|
// 将合并后的图像保存到文件(或根据需要执行其他操作) |
|
|
|
file = new java.io.File(outputFilePath); |
|
|
|
ImageIO.write(combinedImage, "png", file); |
|
|
|
|
|
|
|
String tempSave = outputFilePath; |
|
|
|
String filePath = tempSave; |
|
|
|
|
|
|
|
file = new File(filePath); |
|
|
|
if (!file.exists()) { |
|
|
|
file.createNewFile(); |
|
|
|
} |
|
|
|
// 上传到阿里云 |
|
|
|
DiskFileItemFactory factory = new DiskFileItemFactory(16, null); |
|
|
|
FileItem item = factory.createItem("File", "text/plain", true, file.getName()); |
|
|
|
int bytesRead = 0; |
|
|
|
byte[] buffer = new byte[8192]; |
|
|
|
try { |
|
|
|
FileInputStream fis = new FileInputStream(file); |
|
|
|
OutputStream os = item.getOutputStream(); |
|
|
|
while ((bytesRead = fis.read(buffer, 0, 8192)) != -1) { |
|
|
|
os.write(buffer, 0, bytesRead); |
|
|
|
} |
|
|
|
os.close(); |
|
|
|
fis.close(); |
|
|
|
} catch (IOException e) { |
|
|
|
e.printStackTrace(); |
|
|
|
} |
|
|
|
MultipartFile mf = new CommonsMultipartFile(item); |
|
|
|
String rul = this.uploadAliYunOss(mf); |
|
|
|
|
|
|
|
System.out.println("合并后的图像已保存到" + this.uploadAliYunOss(mf)); |
|
|
|
|
|
|
|
return rul; |
|
|
|
// 将合并后的图像保存到临时文件 |
|
|
|
file = File.createTempFile("combined_", ".png"); |
|
|
|
ImageIO.write(backgroundImage, "png", file); |
|
|
|
|
|
|
|
// 上传到阿里云OSS |
|
|
|
// return this.uploadAliYunOss(Files.readAllBytes(file.toPath()), file.getName()); |
|
|
|
return Files.readAllBytes(file.toPath()); |
|
|
|
} catch (Exception e) { |
|
|
|
e.printStackTrace(); |
|
|
|
log.error("生成合并图片失败", e); |
|
|
|
throw new RuntimeException("生成合并图片失败", e); |
|
|
|
} finally { |
|
|
|
//删除文件 |
|
|
|
if (file.exists()) { |
|
|
|
// 删除临时文件 |
|
|
|
if (file != null && file.exists()) { |
|
|
|
file.delete(); |
|
|
|
} |
|
|
|
} |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -1294,29 +1330,41 @@ public class AppletIndexServiceImpl implements AppletIndexService { |
|
|
|
return map.get("access_token"); |
|
|
|
} |
|
|
|
/** |
|
|
|
* 上传文件至阿里云oss |
|
|
|
* |
|
|
|
* @return |
|
|
|
* 上传文件至阿里云oss - 优化版 |
|
|
|
* 直接使用字节数组上传,减少文件IO操作 |
|
|
|
* |
|
|
|
* @return 上传后的文件路径 |
|
|
|
*/ |
|
|
|
private String uploadAliYunOss(MultipartFile mf) throws Exception { |
|
|
|
private String uploadAliYunOss(byte[] content, String fileName) throws Exception { |
|
|
|
String uploadFile = "WxCodeFile"; |
|
|
|
String fileName = new StringBuffer(mf.getOriginalFilename()).append(".jpg").toString();// 获取文件名 |
|
|
|
String dbpath = uploadFile + File.separator + fileName; |
|
|
|
if (dbpath.contains("\\")) { |
|
|
|
dbpath = dbpath.replace("\\", "/"); |
|
|
|
String dbpath = uploadFile + "/" + fileName; |
|
|
|
|
|
|
|
// 创建OSSClient实例 |
|
|
|
OSS ossClient = null; |
|
|
|
try { |
|
|
|
// 直接获取文件字节数组,避免额外的IO操作 |
|
|
|
|
|
|
|
// 创建OSS客户端 |
|
|
|
ossClient = new OSSClientBuilder().build(endpoint, accessKey, secretKey); |
|
|
|
|
|
|
|
// 设置文件元数据 |
|
|
|
com.aliyun.oss.model.ObjectMetadata metadata = new com.aliyun.oss.model.ObjectMetadata(); |
|
|
|
metadata.setContentType("image/jpeg"); |
|
|
|
metadata.setContentLength(content.length); |
|
|
|
|
|
|
|
// 上传字节数组 |
|
|
|
ossClient.putObject(bucketName, dbpath, new ByteArrayInputStream(content), metadata); |
|
|
|
|
|
|
|
return dbpath; |
|
|
|
} catch (Exception e) { |
|
|
|
log.error("上传文件到阿里云OSS失败", e); |
|
|
|
throw e; |
|
|
|
} finally { |
|
|
|
// 确保关闭OSS客户端 |
|
|
|
if (ossClient != null) { |
|
|
|
ossClient.shutdown(); |
|
|
|
} |
|
|
|
} |
|
|
|
String endpoint = this.endpoint; |
|
|
|
String accessKey = this.accessKey; |
|
|
|
String secretKey = this.secretKey; |
|
|
|
// 创建OSSClient实例。 |
|
|
|
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKey, secretKey); |
|
|
|
// 上传Byte数组。 |
|
|
|
byte[] content = mf.getBytes(); |
|
|
|
String bucketName = this.bucketName; |
|
|
|
ossClient.putObject(bucketName, dbpath, new ByteArrayInputStream(content)); |
|
|
|
// 关闭OSSClient。 |
|
|
|
ossClient.shutdown(); |
|
|
|
return dbpath; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|