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

下面我将详细介绍如何使用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. 配置微信小程序参数

@Configuration
public 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. 用户-推广关系服务

@Service
public 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实现,你可以完整地构建一个支持不同人员生成不同小程序码并能追踪扫码来源的系统。

Java 实现微信小程序不同人员生成不同小程序码并追踪扫码来源的更多相关文章

  1. 微信小程序使用场景延伸:扫码登录、扫码支付

    微信小程序使用场景延伸:扫码登录.扫码支付 小程序最适合的使用场景有哪些?相比大家能列举出来很多,但这个场景,大家可能多数没想到_^ 笔者团队近期接到了一个PC项目:转转游戏租号PC官网,该项目要求在 ...

  2. 行星万象表白墙微信小程序、社交微信小程序,后台完整,支持多区域运营,扫码体验。

    简介 中国目前大概有5000个表白墙,累计用户近3000万,是一个庞大的群体,但现在大都以微信朋友圈为基础进行信息中转,但是这种模式经营者和用户都不友好,尤其是经营者无法变现,用户无法公开评论,这些种 ...

  3. asp.net core 微信扫码支付(扫码支付,H5支付,公众号支付,app支付)之1

    2018-08-13更新生成二维码的方法 在做微信支付前,首先要了解你需要什么方式的微信支付,目前本人做过的支付包含扫码支付.H5支付.公众号支付.App支付等,本人使用的是asp.net mvc c ...

  4. 微信支付之扫码、APP、小程序支付接入详解

    做电商平台的小伙伴都知道,支付服务是必不可少的一部分,今天我们开始就说说支付服务的接入及实现.目前在国内,几乎90%中小公司的支付系统都离不开微信支付和支付宝支付.那么大家要思考了,为什么微信支付和支 ...

  5. 微信公众号支付|微信H5支付|微信扫码支付|小程序支付|APP微信支付解决方案总结

    最近负责的一些项目开发,都用到了微信支付(微信公众号支付.微信H5支付.微信扫码支付.APP微信支付).在开发的过程中,在调试支付的过程中,或多或少都遇到了一些问题,今天总结下,分享,留存. 先说注意 ...

  6. 微信小程序~扫码

    为了让用户减少输入,我们可以把复杂的信息编码成一个二维码,利用宿主环境wx.scanCode这个API调起微信扫一扫,用户扫码之后,wx.scanCode的success回调会收到这个二维码所对应的字 ...

  7. Authing新功能——小程序扫码登录

    近期,Authing 发布了新功能--小程序扫码登录. 小程序扫码登录指使用Authing小程序身份管家在网页端或其它客户端执行微信登录,目前的SDK仅支持客户端JavaScript.其它语言若想使用 ...

  8. php微信支付(仅pc端扫码支付模式二)详细步骤.----仅适合第一次做微信开发的程序员

    本人最近做了微信支付开发,是第一次接触.其中走了很多弯路,遇到的问题也很多.为了让和我一样的新人不再遇到类似的问题,我把我的开发步骤和问题写出来,以供参考. 开发时间是2016/8/10,所以微信支付 ...

  9. 记录:c#实现微信,支付宝扫码支付(一)

    因为公司系统业务需要,这几天了解了一下微信和支付宝扫码支付的接口,并用c#实现了微信和支付宝扫码支付的功能. 微信支付分为6种支付模式:1.付款码支付,2.native支付,3.jsapi支付,4.a ...

  10. Win10环境前后端分离项目基于Vue.js+Django+Python3实现微信(wechat)扫码支付流程(2021年最新攻略)

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_182 之前的一篇文章:mpvue1.0+python3.7+Django2.0.4实现微信小程序的支付功能,主要介绍了微信小程序内 ...

随机推荐

  1. 【ABAQUS文档笔记】ABAQUS刚体单元和可变形单元的review

    学习笔记,帮助文档学习笔记 目录 A. finite element DOF of Elem Order of Elem Formulation of Elem Integration A.1 con ...

  2. 关闭windows计划重启

    前言 windows 总是自动计划更新 解决方案 需要禁用服务 "Windows Update" 和 "更新 Orchestrator 服务" 首先去这里下载P ...

  3. OpenHarmony 开源鸿蒙北向开发——hdc工具安装

    ​ hdc(OpenHarmony Device Connector)是为开发人员提供的用于设备连接调试的命令行工具,该工具需支持部署在 Windows/Linux/Mac 等系统上与 OpenHar ...

  4. Creo 4.0二次开发工具框架搭建

    一.新建MFC DLL工程  二.配置项目属性 附加依赖项中输入:netapi32.lib;psapi.lib;mpr.lib;wsock32.lib;protk_dll_NU.lib;protk_d ...

  5. MFC使用WM_COPYDATA消息进行进程间的通讯

    一.介绍 Windows上MFC应用程序可使用WM_COPYDATA可以完成两个进程之间的通讯.当一个应用向另一个应用传送数据时,发送方需调用SendMessage函数,参数是目的窗口的句柄.传递数据 ...

  6. llamacpp转换hf、vllm运行gguf

    Linux通过huggingface安装大模型 huggingface官网 https://huggingface.co/ wget https://repo.anaconda.com/minicon ...

  7. 技术博客:如何构建AI模拟面试系统(附完整GitHub代码)

    引言:当董明珠.雷军.马斯克和特朗普成为你的面试官 在当今竞争激烈的求职市场中,模拟面试系统正成为开发者提升竞争力的秘密武器.但传统的模拟面试太过平淡,于是我开发了一个多风格AI面试官系统,让你可以体 ...

  8. 推荐Linux命令行运维工具: Wowkey--实现自动化批量化标准化

    WowKey命令行运维工具,Linux设备的自动化.批量化.标准化的运维解决方案,解放运维人,提升企业运维效率和质量. 有人能理解做设备的运营维护工作的痛苦所在吗? 如果你的运维工作中,只维护个位数数 ...

  9. GIS空间索引技术

    地理信息系统(Geography Information System,简称GIS)的主要任务之一是有效地检索空间数据及快速响应不同用户的在线查询.地理空间索引技术和方法是GIS的关键技术.是快速高效 ...

  10. AnnotationAwareAspectJAutoProxyCreator后置处理器的BeanDefinition定义信息导入和其对象实例创建过程

    步骤1 我们从配置类上的@EnableAspectJAutoProxy 注解入手,进入发现这个注解上又有一个@Import(AspectJAutoProxyRegistrar.class)注解, 了解 ...