diff --git a/yudao-framework/yudao-common/pom.xml b/yudao-framework/yudao-common/pom.xml index 85cdbd7..7410c28 100644 --- a/yudao-framework/yudao-common/pom.xml +++ b/yudao-framework/yudao-common/pom.xml @@ -128,6 +128,12 @@ hutool-all + + com.google.zxing + core + 3.3.3 + + com.alibaba transmittable-thread-local diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageCodeController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageCodeController.java new file mode 100644 index 0000000..ebede09 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageCodeController.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.trade.controller.app.brokerage; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.user.BrokerageUserCreateReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageCodeDO; +import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageCodeService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.validation.Valid; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +@Tag(name = "用户 APP - 分销码") +@RestController +@RequestMapping("/trade/brokerage-code") +@Validated +@Slf4j +public class AppBrokerageCodeController { + + @Resource + private BrokerageCodeService brokerageCodeService; + + @GetMapping("/get") + @Operation(summary = "获取用户的分销码") + public CommonResult createBrokerageUser() { + return success(brokerageCodeService.getUserBrokerageCode(getLoginUserId())); + } + + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/BrokerageCodeDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/BrokerageCodeDO.java index 45e04b4..34663a2 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/BrokerageCodeDO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/BrokerageCodeDO.java @@ -43,4 +43,9 @@ public class BrokerageCodeDO extends BaseDO { */ private String code; + /** + * 分销链接 + */ + private String url; + } \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/web/config/TradeBrokerageConfiguration.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/web/config/TradeBrokerageConfiguration.java new file mode 100644 index 0000000..adaae4a --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/web/config/TradeBrokerageConfiguration.java @@ -0,0 +1,17 @@ +package cn.iocoder.yudao.module.trade.framework.web.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +@Component +@ConfigurationProperties("brokerage") +@Data +public class TradeBrokerageConfiguration { + + /** + * app下载地址 + */ + private String downloadUrl; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageCodeService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageCodeService.java index c9abf87..427c696 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageCodeService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageCodeService.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.trade.service.brokerage; -import java.util.*; import javax.validation.*; + import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.code.BrokerageCodePageReqVO; import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.code.BrokerageCodeSaveReqVO; @@ -37,4 +37,8 @@ public interface BrokerageCodeService { */ PageResult getBrokerageCodePage(BrokerageCodePageReqVO pageReqVO); + /** + * 获取用户的分销码 + */ + BrokerageCodeDO getUserBrokerageCode(Long userId); } \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageCodeServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageCodeServiceImpl.java index 873ed8f..9ad7859 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageCodeServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageCodeServiceImpl.java @@ -1,14 +1,24 @@ package cn.iocoder.yudao.module.trade.service.brokerage; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.RandomUtil; +import cn.iocoder.yudao.module.infra.api.file.FileApi; import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.code.BrokerageCodePageReqVO; import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.code.BrokerageCodeSaveReqVO; import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageCodeDO; import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.BrokerageCodeMapper; +import cn.iocoder.yudao.module.trade.framework.web.config.TradeBrokerageConfiguration; +import cn.iocoder.yudao.module.trade.util.PosterPicGen; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; + import javax.annotation.Resource; + import org.springframework.validation.annotation.Validated; +import java.io.FileInputStream; import java.util.*; + import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; @@ -18,13 +28,20 @@ import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.BROKERAGE_C /** * 分销码 Service 实现类 */ +@Slf4j @Service @Validated public class BrokerageCodeServiceImpl implements BrokerageCodeService { + @Resource + private TradeBrokerageConfiguration brokerageConfiguration; + @Resource private BrokerageCodeMapper brokerageCodeMapper; + @Resource + private FileApi fileApi; + @Override public Long createBrokerageCode(BrokerageCodeSaveReqVO createReqVO) { // 插入 @@ -67,4 +84,51 @@ public class BrokerageCodeServiceImpl implements BrokerageCodeService { return brokerageCodeMapper.selectPage(pageReqVO); } + /** + * 获取用户的分销码 + */ + @Override + public BrokerageCodeDO getUserBrokerageCode(Long userId) { + // 查询用户有没有分销码 + BrokerageCodeDO brokerageCode = brokerageCodeMapper.selectOne(BrokerageCodeDO::getMemberId, userId); + if (ObjectUtil.isNotEmpty(brokerageCode)) return brokerageCode; + return generateCode(userId); + } + + /** + * 生成用户的分销码 + */ + private BrokerageCodeDO generateCode(Long userId) { + boolean isRepet = true; + String code = null; + while (isRepet) { + code = RandomUtil.randomNumbers(8); + BrokerageCodeDO brokerageCode = brokerageCodeMapper.selectOne(BrokerageCodeDO::getCode, code); + isRepet = ObjectUtil.isNotEmpty(brokerageCode); + } + String url = generatePosterUrl(code, userId); + BrokerageCodeDO saveObj = BrokerageCodeDO.builder().memberId(userId).code(code).posterPic(generatePosterPic(code, url)).url(url).build(); + brokerageCodeMapper.insert(saveObj); + return saveObj; + } + + /** + * 生成分销海报图 + */ + private String generatePosterPic(String code, String qrCodeUrl) { + try { + byte[] fileInputStream = new PosterPicGen().setCode(code).setQrCodeUrl(qrCodeUrl).gen(); + String file = fileApi.createFile(fileInputStream); + return file; + } catch (Exception e) { + e.printStackTrace(); + log.error("|生成分销海报图|,意外的错误error:|{}|", e.getMessage()); + } + return ""; + } + + private String generatePosterUrl(String code, Long userId) { + return brokerageConfiguration.getDownloadUrl() + "?code=" + code + "&userId=" + userId; + } + } \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/util/PosterPicGen.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/util/PosterPicGen.java new file mode 100644 index 0000000..f9b0f76 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/util/PosterPicGen.java @@ -0,0 +1,96 @@ +package cn.iocoder.yudao.module.trade.util; + + +import cn.hutool.core.io.resource.ResourceUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.extra.qrcode.QrCodeUtil; +import lombok.extern.slf4j.Slf4j; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; + +/** + * 生成海报 + */ +@Slf4j +public class PosterPicGen { + + private Graphics2D graphics; + + private int pageWidth = 375; + + private int pageHeight = 700; + + private String title = "荷塘月色"; + + private String description = "来自缘分的相遇"; + + private String code = ""; + + private String qrCodeUrl = ""; + + private String bottomDescription = "微信无法打开的用户请更换为其他方式扫码"; + + public PosterPicGen setCode(String code) { + this.code = code; + return this; + } + + public PosterPicGen + + setQrCodeUrl(String qrCodeUrl) { + this.qrCodeUrl = qrCodeUrl; + return this; + } + + public byte[] gen() { + try { + BufferedImage baseImage = ImageIO.read(ResourceUtil.getResource("image/base-poster.png")); + baseImage.getScaledInstance(this.pageWidth, this.pageHeight, Image.SCALE_SMOOTH); + graphics = baseImage.createGraphics(); + graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + // 设置 title + graphics.setFont(new Font("PingFang SC, Microsoft YaHei, sans-serif", Font.BOLD, 18)); + graphics.setColor(Color.decode("#333333")); + graphics.drawString(this.title, 84, 60); + // 设置 description + graphics.setFont(new Font("PingFang SC, Microsoft YaHei, sans-serif", Font.PLAIN, 14)); + graphics.setColor(Color.decode("#666666")); + graphics.drawString(this.description, 84, 85); + // 设置 code + writeCenterText(new Font("Arial, sans-serif", Font.BOLD, 28), this.code, 270); + // 设置 bottomDescription + writeCenterText(new Font("PingFang SC, sans-serif", Font.PLAIN, 12), this.bottomDescription, 640); + // 插入二维码 + if (ObjectUtil.isNotEmpty(this.qrCodeUrl)) { + int qrWidth = 150; + int qrHeight = 150; + BufferedImage generate = QrCodeUtil.generate(this.qrCodeUrl, qrWidth, qrHeight); + int x = (baseImage.getWidth() - qrWidth) / 2; + int y = 350; + graphics.drawImage(generate, x, y, qrWidth, qrHeight, null); + } + + graphics.dispose(); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ImageIO.write(baseImage, "png", baos); + return baos.toByteArray(); + } catch (Exception e) { + e.printStackTrace(); + log.error("|生成海报|,意外的错误error:|{}|", e.getMessage()); + return null; + } + } + + private void writeCenterText(Font font, String text, int y) { + graphics.setFont(font); + FontMetrics metrics = graphics.getFontMetrics(font); + int x = (this.pageWidth - metrics.stringWidth(text)) / 2; + graphics.drawString(text, x, y); + } + + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/resources/image/base-poster.png b/yudao-module-mall/yudao-module-trade-biz/src/main/resources/image/base-poster.png new file mode 100644 index 0000000..de2e3d3 Binary files /dev/null and b/yudao-module-mall/yudao-module-trade-biz/src/main/resources/image/base-poster.png differ diff --git a/yudao-server/src/main/resources/application-dev.yaml b/yudao-server/src/main/resources/application-dev.yaml index e568ceb..a6b2d28 100644 --- a/yudao-server/src/main/resources/application-dev.yaml +++ b/yudao-server/src/main/resources/application-dev.yaml @@ -243,4 +243,7 @@ al-config: access-key-secret: EVXWFTS2SB6UkjUVFLhTDBfIvIXgI3 face-scene-id: 1000016045 face-verify-callback-url: https://rj4jv5rwqs.by.takin.cc - face-verify-callback-token: uVuYOzoiQBWPp4A5kPgTddZlKWoSQlzc \ No newline at end of file + face-verify-callback-token: uVuYOzoiQBWPp4A5kPgTddZlKWoSQlzc + +brokerage: + download-url: https://www.baidu.com \ No newline at end of file diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index e65cd85..d46d4e3 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -265,4 +265,7 @@ al-config: access-key-secret: EVXWFTS2SB6UkjUVFLhTDBfIvIXgI3 face-scene-id: 1000016045 face-verify-callback-url: https://rj4jv5rwqs.by.takin.cc - face-verify-callback-token: uVuYOzoiQBWPp4A5kPgTddZlKWoSQlzc \ No newline at end of file + face-verify-callback-token: uVuYOzoiQBWPp4A5kPgTddZlKWoSQlzc + +brokerage: + download-url: https://www.baidu.com \ No newline at end of file diff --git a/yudao-server/src/main/resources/application-prod.yaml b/yudao-server/src/main/resources/application-prod.yaml index 4c61207..7607201 100644 --- a/yudao-server/src/main/resources/application-prod.yaml +++ b/yudao-server/src/main/resources/application-prod.yaml @@ -255,4 +255,7 @@ al-config: access-key-secret: EVXWFTS2SB6UkjUVFLhTDBfIvIXgI3 face-scene-id: 1000016045 face-verify-callback-url: https://rj4jv5rwqs.by.takin.cc - face-verify-callback-token: uVuYOzoiQBWPp4A5kPgTddZlKWoSQlzc \ No newline at end of file + face-verify-callback-token: uVuYOzoiQBWPp4A5kPgTddZlKWoSQlzc + +brokerage: + download-url: https://www.baidu.com \ No newline at end of file