作为一名经历过大学教材采购"血泪史"的老学长,我深知二手教材交易对学生们的重要性。每年开学季,新教材价格动辄几百元,而毕业季大量优质教材又被当作废纸处理,这种资源错配在高校普遍存在。基于这个痛点,我决定开发一个校园二手教材拍卖系统,借助微信小程序这一轻量级平台,让教材流转更高效、更透明。
系统采用Java+SpringBoot的主流技术栈,后端使用MySQL数据库进行数据存储。选择微信小程序作为前端载体,主要考虑到几个因素:首先,小程序无需安装、即用即走,符合学生群体高频次、碎片化的使用习惯;其次,微信生态完善的支付体系和社交传播能力,特别适合二手交易场景;最后,小程序开发成本低,迭代速度快,适合课程设计的开发周期。
后端选择SpringBoot框架主要基于以下考量:
数据库选用MySQL 8.0版本,主要优势包括:
系统采用经典的三层架构,整体分为以下几个核心模块:
用户模块
管理模块
公共服务模块
提示:在模块划分时,特别注意将支付、消息等公共功能单独抽离,避免代码重复,也便于后期维护升级。
小程序端采用官方提供的wx.login接口获取code,后端通过以下流程完成登录验证:
java复制// 1. 获取session_key和openid
String url = "https://api.weixin.qq.com/sns/jscode2session?appid="
+ appId + "&secret=" + appSecret + "&js_code=" + code + "&grant_type=authorization_code";
JSONObject result = HttpClientUtil.doGet(url);
// 2. 生成自定义登录态
String token = JWT.create()
.withClaim("openid", result.getString("openid"))
.withExpiresAt(new Date(System.currentTimeMillis() + EXPIRE_TIME))
.sign(Algorithm.HMAC256(SECRET_KEY));
// 3. 返回token给小程序端
return Result.ok().data("token", token);
关键注意事项:
拍卖功能是系统的核心,主要流程包括:
java复制@PostMapping("/publish")
public Result publish(@RequestBody Book book, @RequestHeader("token") String token) {
// 1. 验证token获取用户ID
String userId = JWTUtil.parseToken(token);
// 2. 参数校验
if(StringUtils.isEmpty(book.getTitle()) || book.getPrice() == null) {
return Result.error("参数不完整");
}
// 3. 设置默认状态和发布时间
book.setStatus(0); // 0-待审核
book.setPublishTime(new Date());
book.setUserId(userId);
// 4. 保存到数据库
bookMapper.insert(book);
return Result.ok();
}
java复制@Scheduled(cron = "0 0/30 * * * ?")
public void checkAuctionStatus() {
// 查询即将结束的拍卖
List<Book> endingBooks = bookMapper.selectEndingSoon(new Date());
for(Book book : endingBooks) {
// 检查是否有出价
if(book.getHighestBid() != null) {
// 生成订单
Order order = createOrder(book);
orderMapper.insert(order);
// 通知买卖双方
notifyUsers(book, order);
}
// 更新状态
book.setStatus(2); // 2-已结束
bookMapper.updateById(book);
}
}
系统采用微信支付完成交易闭环,关键实现步骤:
java复制public Map<String, String> createPayment(Order order) throws Exception {
Map<String, String> data = new HashMap<>();
data.put("appid", wxPayConfig.getAppId());
data.put("mch_id", wxPayConfig.getMchId());
data.put("nonce_str", WXPayUtil.generateNonceStr());
data.put("body", "二手教材购买-" + order.getBookTitle());
data.put("out_trade_no", order.getOrderNo());
data.put("total_fee", String.valueOf(order.getActualPrice()));
data.put("spbill_create_ip", order.getClientIp());
data.put("notify_url", wxPayConfig.getNotifyUrl());
data.put("trade_type", "JSAPI");
data.put("openid", order.getBuyerOpenid());
// 签名并生成XML请求
String signedXml = WXPayUtil.generateSignedXml(data, wxPayConfig.getKey());
// 调用微信支付接口
String response = HttpClientUtil.doPost("https://api.mch.weixin.qq.com/pay/unifiedorder", signedXml);
return WXPayUtil.xmlToMap(response);
}
重要安全提示:支付回调接口必须做好签名验证和幂等处理,防止重复通知导致资金异常。
书籍表(book)
sql复制CREATE TABLE `book` (
`id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint NOT NULL COMMENT '发布者ID',
`title` varchar(100) NOT NULL COMMENT '书籍标题',
`author` varchar(50) DEFAULT NULL COMMENT '作者',
`publisher` varchar(50) DEFAULT NULL COMMENT '出版社',
`isbn` varchar(20) DEFAULT NULL COMMENT 'ISBN号',
`cover_url` varchar(255) DEFAULT NULL COMMENT '封面图',
`original_price` decimal(10,2) DEFAULT NULL COMMENT '原价',
`current_price` decimal(10,2) NOT NULL COMMENT '当前价格',
`min_price` decimal(10,2) DEFAULT NULL COMMENT '最低接受价',
`status` tinyint NOT NULL DEFAULT '0' COMMENT '0-待审核 1-拍卖中 2-已结束 3-已下架',
`start_time` datetime DEFAULT NULL COMMENT '拍卖开始时间',
`end_time` datetime DEFAULT NULL COMMENT '拍卖结束时间',
`view_count` int DEFAULT '0' COMMENT '浏览数',
`description` text COMMENT '详细描述',
PRIMARY KEY (`id`),
KEY `idx_user` (`user_id`),
KEY `idx_status` (`status`),
KEY `idx_time` (`start_time`,`end_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
出价记录表(bid)
sql复制CREATE TABLE `bid` (
`id` bigint NOT NULL AUTO_INCREMENT,
`book_id` bigint NOT NULL,
`user_id` bigint NOT NULL,
`price` decimal(10,2) NOT NULL,
`bid_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`is_auto_bid` tinyint(1) DEFAULT '0' COMMENT '是否自动出价',
PRIMARY KEY (`id`),
KEY `idx_book` (`book_id`),
KEY `idx_user` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
推荐使用以下最低配置:
安全加固措施:
基础监控项配置示例(Prometheus格式):
yaml复制- job_name: 'springboot'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['localhost:8080']
alerting:
rules:
- alert: HighErrorRate
expr: rate(http_server_requests_errors_total[1m]) > 0.1
for: 5m
labels:
severity: critical
annotations:
summary: "High error rate on {{ $labels.instance }}"
图片上传失败:
真机调试样式异常:
支付回调处理:
java复制@SpringBootApplication
public class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class)
.web(WebApplicationType.SERVLET)
.lazyInitialization(true) // 延迟初始化
.run(args);
}
}
推荐系统集成:
即时通讯功能:
数据分析看板:
这个项目从零开始完整实现大约需要3-4周开发时间,关键是要把握好功能优先级,先实现核心交易闭环,再逐步完善辅助功能。在实际部署时,建议先用小范围测试收集反馈,再逐步扩大用户规模。