Merge remote-tracking branch 'origin/main'
This commit is contained in:
commit
ea2bff19a9
5 files changed
+81
-8
No files matched your search
+8
@@ -2,9 +2,13 @@ package cn.iocoder.yudao.module.product.controller.admin.device.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import com.alibaba.excel.annotation.*;
|
||||
|
||||
@Schema(description = "管理后台 - 贩卖机信息 Response VO")
|
||||
@@ -28,6 +32,10 @@ public class DeviceRespVO {
|
||||
@ExcelProperty("访问商品地址")
|
||||
private String productUrl;
|
||||
|
||||
@Schema(description = "设备上的小程序二维码地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn")
|
||||
@ExcelProperty("设备上的小程序二维码地址")
|
||||
private String productDeviceUrl;
|
||||
|
||||
@Schema(description = "文件地址", example = "https://www.iocoder.cn")
|
||||
@ExcelProperty("文件地址")
|
||||
private String fileUrl;
|
||||
|
||||
+4
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.product.controller.admin.device.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
|
||||
import java.util.*;
|
||||
import javax.validation.constraints.*;
|
||||
|
||||
@@ -23,6 +24,9 @@ public class DeviceSaveReqVO {
|
||||
// @NotEmpty(message = "访问商品地址不能为空")
|
||||
private String productUrl;
|
||||
|
||||
@Schema(description = "设备上的小程序二维码地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn")
|
||||
private String productDeviceUrl;
|
||||
|
||||
@Schema(description = "文件地址", example = "https://www.iocoder.cn")
|
||||
private String fileUrl;
|
||||
|
||||
|
||||
+9
@@ -1,9 +1,11 @@
|
||||
package cn.iocoder.yudao.module.product.dal.dataobject.device;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
|
||||
@@ -37,8 +39,15 @@ public class DeviceDO extends BaseDO {
|
||||
private String deviceId;
|
||||
/**
|
||||
* 访问商品地址
|
||||
* 小程序二维码地址
|
||||
*/
|
||||
private String productUrl;
|
||||
|
||||
/**
|
||||
* 设备上的小程序二维码地址
|
||||
*/
|
||||
private String productDeviceUrl;
|
||||
|
||||
/**
|
||||
* 文件地址
|
||||
*/
|
||||
|
||||
+54
-2
@@ -14,12 +14,18 @@ import org.springframework.http.*;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
import cn.iocoder.yudao.module.product.controller.admin.device.vo.*;
|
||||
import cn.iocoder.yudao.module.product.dal.dataobject.device.DeviceDO;
|
||||
@@ -116,7 +122,7 @@ public class DeviceServiceImpl implements DeviceService {
|
||||
DeviceDO updateObj = BeanUtils.toBean(updateReqVO, DeviceDO.class);
|
||||
DispenseRequestBo request = new DispenseRequestBo();
|
||||
request.setDeviceId(updateReqVO.getDeviceId());
|
||||
request.setMessage(updateReqVO.getProductUrl() + "," + updateReqVO.getFileUrl());
|
||||
request.setMessage(updateReqVO.getProductDeviceUrl() + "," + updateReqVO.getFileUrl());
|
||||
// 设置请求头
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
@@ -157,7 +163,7 @@ public class DeviceServiceImpl implements DeviceService {
|
||||
@Override
|
||||
public String refreshWechantCode(Long id) {
|
||||
DeviceDO deviceDO = deviceMapper.selectById(id);
|
||||
if ( deviceDO== null|| deviceDO.getDeviceId()==null) {
|
||||
if (deviceDO == null || deviceDO.getDeviceId() == null) {
|
||||
throw exception(DEVICE_NOT_EXISTS);
|
||||
}
|
||||
|
||||
@@ -173,6 +179,7 @@ public class DeviceServiceImpl implements DeviceService {
|
||||
try {
|
||||
// 生成微信小程序二维码
|
||||
byte[] imageByte = socialClientApi.getWxaQrcode(codeObj);
|
||||
String deviceWechatQrCode = disposeWechatQrcodeImage(imageByte);
|
||||
// 保存二维码
|
||||
String file = fileApi.createFile(imageByte);
|
||||
if (ObjectUtil.isEmpty(file)) {
|
||||
@@ -181,6 +188,9 @@ public class DeviceServiceImpl implements DeviceService {
|
||||
}
|
||||
// 更新一下
|
||||
DeviceDO updateObj = DeviceDO.builder().id(id).productUrl(file).build();
|
||||
if (ObjectUtil.isNotEmpty(deviceWechatQrCode)) {
|
||||
updateObj.setProductDeviceUrl(deviceWechatQrCode);
|
||||
}
|
||||
deviceMapper.updateById(updateObj);
|
||||
// 刷新一下硬件设备
|
||||
updateDevice(BeanUtil.toBean(deviceMapper.selectById(id), DeviceSaveReqVO.class));
|
||||
@@ -233,4 +243,46 @@ public class DeviceServiceImpl implements DeviceService {
|
||||
return deviceMapper.updateDeviceLastChannel(deviceId, cabinetChannel);
|
||||
}
|
||||
|
||||
// 处理小程序二维码图片
|
||||
private String disposeWechatQrcodeImage(byte[] imageByte) {
|
||||
int baseMapWidth = 1920;
|
||||
int baseMapHeight = 1080;
|
||||
|
||||
try {
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(imageByte);
|
||||
BufferedImage qrImage = ImageIO.read(bais);
|
||||
|
||||
baseMapWidth = qrImage.getWidth() + 20;
|
||||
|
||||
// 创建白色背景图片
|
||||
BufferedImage whiteBackgroundImage = new BufferedImage(baseMapWidth, baseMapHeight, BufferedImage.TYPE_INT_RGB);
|
||||
|
||||
// 填充白色背景
|
||||
Graphics2D g2d = whiteBackgroundImage.createGraphics();
|
||||
g2d.setColor(Color.WHITE);
|
||||
g2d.fillRect(0, 0, baseMapWidth, baseMapHeight);
|
||||
|
||||
// 计算二维码在背景图中的居中位置
|
||||
int qrWidth = qrImage.getWidth();
|
||||
int qrHeight = qrImage.getHeight();
|
||||
int x = (baseMapWidth - qrWidth) / 2;
|
||||
int y = (baseMapHeight - qrHeight) / 2;
|
||||
|
||||
// 将二维码绘制到白色背景的居中位置
|
||||
g2d.drawImage(qrImage, x, y, null);
|
||||
g2d.dispose();
|
||||
|
||||
// 转换回byte数组
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ImageIO.write(whiteBackgroundImage, "png", baos);
|
||||
byte[] resultImageInByte = baos.toByteArray();
|
||||
|
||||
return fileApi.createFile(resultImageInByte);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
log.error("[处理小程序二维码图片错误]:原因: {}", e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+6
-6
@@ -74,7 +74,7 @@ public class SocialClientServiceImpl implements SocialClientService {
|
||||
|
||||
/**
|
||||
* 小程序码要打开的小程序版本
|
||||
*
|
||||
* <p>
|
||||
* 1. release:正式版
|
||||
* 2. trial:体验版
|
||||
* 3. developer:开发版
|
||||
@@ -83,7 +83,7 @@ public class SocialClientServiceImpl implements SocialClientService {
|
||||
public String envVersion;
|
||||
/**
|
||||
* 订阅消息跳转小程序类型
|
||||
*
|
||||
* <p>
|
||||
* 1. developer:开发版
|
||||
* 2. trial:体验版
|
||||
* 3. formal:正式版
|
||||
@@ -102,10 +102,10 @@ public class SocialClientServiceImpl implements SocialClientService {
|
||||
private StringRedisTemplate stringRedisTemplate; // WxMpService 需要使用到,所以在 Service 注入了它
|
||||
/**
|
||||
* 缓存 WxMpService 对象
|
||||
*
|
||||
* <p>
|
||||
* key:使用微信公众号的 appId + secret 拼接,即 {@link SocialClientDO} 的 clientId 和 clientSecret 属性。
|
||||
* 为什么 key 使用这种格式?因为 {@link SocialClientDO} 在管理后台可以变更,通过这个 key 存储它的单例。
|
||||
*
|
||||
* <p>
|
||||
* 为什么要做 WxMpService 缓存?因为 WxMpService 构建成本比较大,所以尽量保证它是单例。
|
||||
*/
|
||||
private final LoadingCache<String, WxMpService> wxMpServiceCache = CacheUtils.buildAsyncReloadingCache(
|
||||
@@ -126,7 +126,7 @@ public class SocialClientServiceImpl implements SocialClientService {
|
||||
private WxMaProperties wxMaProperties;
|
||||
/**
|
||||
* 缓存 WxMaService 对象
|
||||
*
|
||||
* <p>
|
||||
* 说明同 {@link #wxMpServiceCache} 变量
|
||||
*/
|
||||
private final LoadingCache<String, WxMaService> wxMaServiceCache = CacheUtils.buildAsyncReloadingCache(
|
||||
@@ -407,7 +407,7 @@ public class SocialClientServiceImpl implements SocialClientService {
|
||||
|
||||
/**
|
||||
* 校验社交应用是否重复,需要保证 userType + socialType 唯一
|
||||
*
|
||||
* <p>
|
||||
* 原因是,不同端(userType)选择某个社交登录(socialType)时,需要通过 {@link #buildAuthRequest(Integer, Integer)} 构建对应的请求
|
||||
*
|
||||
* @param id 编号
|
||||
|
||||
Reference in new issue
Block a user