1. 项目概述与核心功能解析
这个基于Java SSM框架的在线花卉商城系统,是我在2022年为本地一家连锁花店开发的电商解决方案。系统最核心的价值在于完整实现了从商品展示到支付结算的闭环,特别针对鲜花这类时效性强的商品设计了库存预警和配送时间选择功能。
项目采用经典的SSM(Spring+SpringMVC+MyBatis)架构,前端使用JSP+Bootstrap实现响应式布局。支付模块同时集成了微信支付和支付宝沙箱环境,在实际运营中单日最高处理过327笔真实订单。系统包含以下核心模块:
- 商品管理:支持多维度分类(节日/用途/价格区间)、库存实时更新
- 会员体系:积分、优惠券、收藏夹等常规功能
- 订单系统:含特色配送时间选择(精确到2小时时段)
- 支付网关:双渠道支付+异步通知处理
- 后台管理:数据看板、销售统计等
提示:鲜花类电商要特别注意商品有效期的处理,本系统采用"预售+现货"混合模式,数据库中用valid_until字段标记每批次的可用截止时间。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 开发环境搭建与关键技术选型
2.1 基础环境配置
在IntelliJ IDEA 2021.3环境下开发,建议使用以下配置:
- JDK 1.8(实测17版本会有Lombok兼容性问题)
- Tomcat 9.0
- MySQL 5.7(必须开启InnoDB引擎)
- Maven 3.6.3
关键依赖项说明:
xml复制<!-- 支付相关核心依赖 -->
<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>3.0.9</version>
</dependency>
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.10.97.ALL</version>
</dependency>
<!-- 解决微信支付XML解析问题 -->
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.18</version>
</dependency>
2.2 支付模块技术决策
支付方案选择时,我们对比了三种实现方式:
- 直接调用官方SDK(最终选择方案)
- 使用第三方聚合支付(如Ping++)
- 银行直连(复杂度太高)
选择官方SDK的主要考虑:
- 微信支付文档更新频繁,SDK能保持兼容
- 支付宝沙箱环境完善,测试方便
- 避免第三方服务额外费用
3. 核心业务逻辑实现细节
3.1 商品库存的并发控制
鲜花库存需要处理高并发减库存问题,我们采用乐观锁实现:
java复制// FlowerMapper.xml
<update id="reduceStock">
UPDATE flower
SET stock = stock - #{quantity}
WHERE id = #{id} AND stock >= #{quantity}
</update>
// 业务层处理
public boolean purchase(Long flowerId, Integer quantity) {
int rows = flowerMapper.reduceStock(flowerId, quantity);
if (rows == 0) {
throw new RuntimeException("库存不足");
}
// 记录库存变更日志...
}
3.2 支付状态机设计
支付流程的状态转换是关键难点,我们定义了6种状态:
mermaid复制stateDiagram
[*] --> UNPAID
UNPAID --> PAYING : 用户发起支付
PAYING --> PAID : 支付成功
PAYING --> FAILED : 支付失败
PAID --> SHIPPED : 发货
FAILED --> CLOSED : 超时未处理
对应数据库字段:
sql复制`pay_status` ENUM('UNPAID','PAYING','PAID','FAILED','CLOSED','REFUNDED')
4. 支付模块深度解析
4.1 微信支付集成实践
微信JSAPI支付的核心流程:
- 生成预付订单(统一下单接口)
- 获取paySign等前端参数
- 前端调起支付窗口
- 处理异步通知
关键代码片段:
java复制// 统一下单
WXPay wxpay = new WXPay(config);
Map<String, String> params = new HashMap<>();
params.put("body", "玫瑰礼盒 - 花语商城");
params.put("out_trade_no", orderNo);
params.put("total_fee", String.valueOf(amount));
params.put("spbill_create_ip", request.getRemoteAddr());
params.put("notify_url", "https://yourdomain.com/pay/notify");
params.put("trade_type", "JSAPI");
params.put("openid", openid);
Map<String, String> result = wxpay.unifiedOrder(params);
4.2 支付宝沙箱对接
支付宝集成时特别注意:
- 沙箱环境需要单独申请商家/买家账号
- 验签必须使用支付宝公钥(非应用公钥)
- 异步通知处理要幂等
配置示例:
properties复制# application-pay.properties
alipay.appId=202100xxxxxx
alipay.gateway=https://openapi.alipaydev.com/gateway.do
alipay.merchantPrivateKey=MIICXQIBAAKBgQDk...
alipay.alipayPublicKey=MIGfMA0GCSqGSIb3...
alipay.notifyUrl=https://yourdomain.com/pay/alipay/notify
alipay.returnUrl=https://yourdomain.com/pay/success
alipay.charset=utf-8
alipay.signType=RSA2
5. 典型问题排查与优化
5.1 支付超时问题
我们曾遇到15%的支付超时率,排查发现:
- 微信支付默认超时2小时,鲜花业务需要缩短
- 解决方案:在下单时显式设置time_expire
java复制// 设置30分钟过期
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
Calendar now = Calendar.getInstance();
now.add(Calendar.MINUTE, 30);
params.put("time_expire", sdf.format(now.getTime()));
5.2 库存超卖问题
压力测试时出现的极端情况:
- 乐观锁在超高并发下仍可能失效
- 最终方案:Redis分布式锁 + 数据库乐观锁双保险
java复制public boolean safeReduceStock(Long flowerId, int quantity) {
String lockKey = "stock_lock:" + flowerId;
try {
// 获取分布式锁(等待3秒,持有10秒)
boolean locked = redisTemplate.opsForValue()
.setIfAbsent(lockKey, "1", 10, TimeUnit.SECONDS);
if (!locked) {
throw new RuntimeException("系统繁忙,请重试");
}
return flowerMapper.reduceStock(flowerId, quantity) > 0;
} finally {
redisTemplate.delete(lockKey);
}
}
6. 项目部署与运维实践
6.1 生产环境配置建议
根据实际运营经验推荐:
- 服务器:2核4G起步(阿里云ECS)
- 数据库:RDS MySQL 5.7 高可用版
- 支付证书:定期巡检(微信证书每月更新)
- 监控:配置支付失败告警(阈值>5%)
关键JVM参数:
code复制-server -Xms1024m -Xmx1024m -XX:MaxMetaspaceSize=256m
-XX:+UseG1GC -XX:MaxGCPauseMillis=200
6.2 安全防护措施
必须实施的防护:
- 支付接口防重放攻击(nonce_str+timestamp)
- SQL注入过滤(使用MyBatis预编译)
- XSS防护(自定义JSP标签处理输出)
- 定期更换支付密钥(建议季度更新)
7. 扩展功能与二次开发建议
对于想扩展功能的开发者,可以考虑:
- 增加虚拟商品支持(电子贺卡等)
- 对接物流API实现实时轨迹
- 会员等级体系(基于消费金额)
- 拼团/秒杀等营销功能
示例:秒杀功能核心逻辑
java复制@Transactional
public SeckillResult executeSeckill(Long seckillId, Long userId) {
// 1. 校验秒杀时间
Seckill seckill = seckillMapper.selectById(seckillId);
if (seckill.getStartTime().after(new Date())) {
return SeckillResult.error("秒杀未开始");
}
// 2. Redis原子减库存
Long stock = redisTemplate.opsForValue()
.decrement("seckill:stock:" + seckillId);
if (stock < 0) {
return SeckillResult.error("已售罄");
}
// 3. 创建订单(略)
return SeckillResult.success(order);
}
在实际开发中,支付模块要特别注意测试各种边界情况:网络中断、重复支付、部分支付成功等。我们项目中最有价值的经验是建立了完整的支付对账机制,每天凌晨自动核对三方支付记录与系统订单,这个功能帮客户发现了多次金额不符的情况。
