写点什么

Java 后台实现微信小程序不同人员生成不同小程序码并追踪扫码来源

  • 2025-06-05
    福建
  • 本文字数:4183 字

    阅读完需:约 14 分钟

下面我将详细介绍如何使用 Java 后台实现这一功能。


一、整体架构设计


  1. 前端:微信小程序

  2. 后端:Java (Spring Boot)

  3. 数据库:MySQL/其他

  4. 微信接口:调用微信小程序码生成 API


二、数据库设计


1. 推广人员表(promoter)

CREATE TABLE `promoter` (  `id` bigint NOT NULL AUTO_INCREMENT,  `name` varchar(50) NOT NULL COMMENT '推广人员姓名',  `mobile` varchar(20) COMMENT '联系电话',  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,  PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
复制代码


2. 用户-推广关系表(user_promoter_relation)

CREATE TABLE `user_promoter_relation` (  `id` bigint NOT NULL AUTO_INCREMENT,  `user_id` varchar(64) NOT NULL COMMENT '小程序用户openid',  `promoter_id` bigint NOT NULL COMMENT '推广人员ID',  `first_scan_time` datetime NOT NULL COMMENT '首次扫码时间',  `last_scan_time` datetime NOT NULL COMMENT '最近扫码时间',  `scan_count` int NOT NULL DEFAULT '1' COMMENT '扫码次数',  PRIMARY KEY (`id`),  UNIQUE KEY `idx_user_promoter` (`user_id`,`promoter_id`),  KEY `idx_promoter` (`promoter_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
复制代码


三、Java 后端实现


1. 添加微信小程序 Java SDK 依赖

<dependency>    <groupId>com.github.binarywang</groupId>    <artifactId>weixin-java-miniapp</artifactId>    <version>4.1.0</version></dependency>
复制代码


2. 配置微信小程序参数

@Configurationpublic class WxMaConfiguration {        @Value("${wx.miniapp.appid}")    private String appid;        @Value("${wx.miniapp.secret}")    private String secret;        @Bean    public WxMaService wxMaService() {        WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl();        config.setAppid(appid);        config.setSecret(secret);                WxMaService service = new WxMaServiceImpl();        service.setWxMaConfig(config);        return service;    }}
复制代码


3. 生成带参数的小程序码

@RestController@RequestMapping("/api/qrcode")public class QrCodeController {        @Autowired    private WxMaService wxMaService;        @Autowired    private PromoterService promoterService;        /**     * 生成推广二维码     * @param promoterId 推广人员ID     * @return 二维码图片字节流     */    @GetMapping("/generate")    public void generatePromoterQrCode(@RequestParam Long promoterId,                                      HttpServletResponse response) throws IOException {        // 验证推广人员是否存在        Promoter promoter = promoterService.getById(promoterId);        if (promoter == null) {            throw new RuntimeException("推广人员不存在");        }                // 生成小程序码        String scene = "promoterId=" + promoterId;        WxMaQrcodeService qrcodeService = wxMaService.getQrcodeService();        File qrCodeFile = qrcodeService.createWxaCodeUnlimit(scene, "pages/index/index", 430, true, null, false);                // 返回图片流        response.setContentType("image/jpeg");        try (InputStream in = new FileInputStream(qrCodeFile);             OutputStream out = response.getOutputStream()) {            byte[] buffer = new byte[1024];            int len;            while ((len = in.read(buffer)) != -1) {                out.write(buffer, 0, len);            }        }    }}
复制代码


4. 处理扫码进入事件

@RestController@RequestMapping("/api/track")public class TrackController {        @Autowired    private UserPromoterRelationService relationService;        /**     * 记录用户扫码行为     * @param dto 包含用户信息和推广信息     * @return 操作结果     */    @PostMapping("/scan")    public Result trackScan(@RequestBody ScanTrackDTO dto) {        // 解析scene参数        String scene = dto.getScene();        Map<String, String> sceneParams = parseScene(scene);        String promoterIdStr = sceneParams.get("promoterId");                if (StringUtils.isBlank(promoterIdStr)) {            return Result.fail("缺少推广人员参数");        }                try {            Long promoterId = Long.parseLong(promoterIdStr);            relationService.recordUserScan(dto.getOpenid(), promoterId);            return Result.success();        } catch (NumberFormatException e) {            return Result.fail("推广人员参数格式错误");        }    }        private Map<String, String> parseScene(String scene) {        Map<String, String> params = new HashMap<>();        if (StringUtils.isBlank(scene)) {            return params;        }                String[] pairs = scene.split("&");        for (String pair : pairs) {            String[] kv = pair.split("=");            if (kv.length == 2) {                params.put(kv[0], kv[1]);            }        }        return params;    }}
复制代码


5. 用户-推广关系服务

@Servicepublic class UserPromoterRelationServiceImpl implements UserPromoterRelationService {        @Autowired    private UserPromoterRelationMapper relationMapper;        @Override    @Transactional    public void recordUserScan(String openid, Long promoterId) {        // 查询是否已有记录        UserPromoterRelation relation = relationMapper.selectByUserAndPromoter(openid, promoterId);                Date now = new Date();        if (relation == null) {            // 新建关系记录            relation = new UserPromoterRelation();            relation.setUserId(openid);            relation.setPromoterId(promoterId);            relation.setFirstScanTime(now);            relation.setLastScanTime(now);            relation.setScanCount(1);            relationMapper.insert(relation);        } else {            // 更新已有记录            relation.setLastScanTime(now);            relation.setScanCount(relation.getScanCount() + 1);            relationMapper.updateById(relation);        }    }}
复制代码


四、小程序前端处理


在小程序的 app.js 中处理扫码进入的场景:

App({  onLaunch: function(options) {    // 处理扫码进入的情况    if (options.scene === 1047 || options.scene === 1048 || options.scene === 1049) {      // 这些scene值表示是通过扫码进入      const scene = decodeURIComponent(options.query.scene);            // 上报扫码信息到后端      wx.request({        url: 'https://yourdomain.com/api/track/scan',        method: 'POST',        data: {          scene: scene,          openid: this.globalData.openid // 需要先获取用户openid        },        success: function(res) {          console.log('扫码记录成功', res);        }      });    }  }})
复制代码


五、数据统计接口实现

@RestController@RequestMapping("/api/stat")public class StatController {        @Autowired    private UserPromoterRelationMapper relationMapper;        /**     * 获取推广人员业绩统计     * @param promoterId 推广人员ID     * @param startDate 开始日期     * @param endDate 结束日期     * @return 统计结果     */    @GetMapping("/promoter")    public Result getPromoterStats(@RequestParam Long promoterId,                                 @RequestParam(required = false) @DateTimeFormat(pattern="yyyy-MM-dd") Date startDate,                                 @RequestParam(required = false) @DateTimeFormat(pattern="yyyy-MM-dd") Date endDate) {                // 构建查询条件        QueryWrapper<UserPromoterRelation> query = new QueryWrapper<>();        query.eq("promoter_id", promoterId);                if (startDate != null) {            query.ge("first_scan_time", startDate);        }        if (endDate != null) {            query.le("first_scan_time", endDate);        }                // 执行查询        int totalUsers = relationMapper.selectCount(query);        List<Map<String, Object>> dailyStats = relationMapper.selectDailyStatsByPromoter(promoterId, startDate, endDate);                // 返回结果        Map<String, Object> result = new HashMap<>();        result.put("totalUsers", totalUsers);        result.put("dailyStats", dailyStats);                return Result.success(result);    }}
复制代码


六、安全注意事项


  1. 参数校验:所有传入的 promoterId 需要验证是否存在

  2. 防刷机制:限制同一用户频繁上报扫码记录

  3. HTTPS:确保所有接口使用 HTTPS 协议

  4. 权限控制:推广数据统计接口需要添加权限验证

  5. 日志记录:记录所有二维码生成和扫码行为


七、扩展功能建议


  1. 二级分销:可以扩展支持多级推广关系

  2. 奖励机制:根据扫码用户的活动情况给推广人员奖励

  3. 实时通知:当有新用户扫码时,实时通知推广人员

  4. 数据分析:提供更详细的数据分析报表


通过以上 Java 实现,你可以完整地构建一个支持不同人员生成不同小程序码并能追踪扫码来源的系统。


文章转载自:VipSoft

原文链接:https://www.cnblogs.com/vipsoft/p/18910003

体验地址:http://www.jnpfsoft.com/?from=001YH

用户头像

还未添加个人签名 2025-04-01 加入

还未添加个人简介

评论

发布
暂无评论
Java后台实现微信小程序不同人员生成不同小程序码并追踪扫码来源_Java_电子尖叫食人鱼_InfoQ写作社区