1. 积分商城概述

积分商城是现代电商平台的重要组成部分,通过积分系统激励用户参与平台活动,提升用户粘性和活跃度。本文将详细介绍积分系统、商城功能、积分兑换、订单管理和用户权益的完整解决方案。

1.1 核心功能

  1. 积分系统: 积分获取、消费、管理
  2. 商城功能: 商品展示、分类、搜索
  3. 积分兑换: 积分兑换商品、服务
  4. 订单管理: 兑换订单处理、状态跟踪
  5. 用户权益: 会员等级、特权管理

1.2 技术架构

1
2
3
4
5
用户操作 → 积分系统 → 商城服务 → 订单管理 → 物流配送
↓ ↓ ↓ ↓ ↓
积分获取 → 积分消费 → 商品兑换 → 订单处理 → 权益发放
↓ ↓ ↓ ↓ ↓
等级提升 → 特权管理 → 库存管理 → 状态跟踪 → 用户反馈

2. 积分商城配置

2.1 Maven依赖配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<!-- pom.xml -->
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- Spring Boot Data JPA -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<!-- Spring Boot Data Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>

<!-- Redis客户端 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
</dependencies>

2.2 积分商城配置类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/**
* 积分商城配置类
*/
@Configuration
public class PointsMallConfig {

@Value("${points.mall.default-level:1}")
private int defaultLevel;

@Value("${points.mall.max-level:10}")
private int maxLevel;

@Value("${points.mall.points-per-level:1000}")
private int pointsPerLevel;

@Value("${points.mall.exchange-rate:100}")
private int exchangeRate;

/**
* 积分商城配置属性
*/
@Bean
public PointsMallProperties pointsMallProperties() {
return PointsMallProperties.builder()
.defaultLevel(defaultLevel)
.maxLevel(maxLevel)
.pointsPerLevel(pointsPerLevel)
.exchangeRate(exchangeRate)
.build();
}

/**
* 积分服务
*/
@Bean
public PointsService pointsService() {
return new PointsService(pointsMallProperties());
}

/**
* 商城服务
*/
@Bean
public MallService mallService() {
return new MallService(pointsMallProperties());
}

/**
* 兑换服务
*/
@Bean
public ExchangeService exchangeService() {
return new ExchangeService(pointsMallProperties());
}
}

/**
* 积分商城配置属性
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PointsMallProperties {
private int defaultLevel;
private int maxLevel;
private int pointsPerLevel;
private int exchangeRate;

// 积分配置
private Map<String, Integer> pointsRules = new HashMap<>();
private int maxPointsPerDay = 10000;
private int maxPointsPerMonth = 100000;

// 商城配置
private int maxExchangePerDay = 10;
private int maxExchangePerMonth = 100;
private boolean enableAutoRestock = true;

// 等级配置
private Map<Integer, LevelConfig> levelConfigs = new HashMap<>();
private boolean enableLevelUpReward = true;
private int levelUpRewardPoints = 1000;
}

3. 数据模型定义

3.1 积分商城数据模型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/**
* 用户积分模型
*/
@Entity
@Table(name = "user_points")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserPoints {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name = "user_id", nullable = false)
private Long userId;

@Column(name = "total_points", nullable = false)
private Integer totalPoints;

@Column(name = "available_points", nullable = false)
private Integer availablePoints;

@Column(name = "used_points", nullable = false)
private Integer usedPoints;

@Column(name = "level", nullable = false)
private Integer level;

@Column(name = "create_time", nullable = false)
private LocalDateTime createTime;

@Column(name = "update_time", nullable = false)
private LocalDateTime updateTime;
}

/**
* 积分记录模型
*/
@Entity
@Table(name = "points_record")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PointsRecord {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name = "user_id", nullable = false)
private Long userId;

@Column(name = "points", nullable = false)
private Integer points;

@Column(name = "type", nullable = false)
private String type; // EARN, SPEND, REFUND, EXPIRED

@Column(name = "source", nullable = false)
private String source; // LOGIN, PURCHASE, EXCHANGE, ACTIVITY

@Column(name = "description")
private String description;

@Column(name = "order_id")
private Long orderId;

@Column(name = "create_time", nullable = false)
private LocalDateTime createTime;
}

/**
* 商城商品模型
*/
@Entity
@Table(name = "mall_product")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MallProduct {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name = "name", nullable = false)
private String name;

@Column(name = "description")
private String description;

@Column(name = "points_price", nullable = false)
private Integer pointsPrice;

@Column(name = "cash_price", precision = 15, scale = 2)
private BigDecimal cashPrice;

@Column(name = "category", nullable = false)
private String category;

@Column(name = "image_url")
private String imageUrl;

@Column(name = "stock", nullable = false)
private Integer stock;

@Column(name = "status", nullable = false)
private String status; // ACTIVE, INACTIVE, OUT_OF_STOCK

@Column(name = "sort_order", nullable = false)
private Integer sortOrder;

@Column(name = "create_time", nullable = false)
private LocalDateTime createTime;

@Column(name = "update_time", nullable = false)
private LocalDateTime updateTime;
}

/**
* 兑换订单模型
*/
@Entity
@Table(name = "exchange_order")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ExchangeOrder {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name = "order_no", nullable = false, unique = true)
private String orderNo;

@Column(name = "user_id", nullable = false)
private Long userId;

@Column(name = "product_id", nullable = false)
private Long productId;

@Column(name = "product_name", nullable = false)
private String productName;

@Column(name = "points_price", nullable = false)
private Integer pointsPrice;

@Column(name = "quantity", nullable = false)
private Integer quantity;

@Column(name = "total_points", nullable = false)
private Integer totalPoints;

@Column(name = "status", nullable = false)
private String status; // PENDING, CONFIRMED, SHIPPED, DELIVERED, CANCELLED

@Column(name = "shipping_address")
private String shippingAddress;

@Column(name = "contact_phone")
private String contactPhone;

@Column(name = "remark")
private String remark;

@Column(name = "create_time", nullable = false)
private LocalDateTime createTime;

@Column(name = "update_time", nullable = false)
private LocalDateTime updateTime;
}

/**
* 用户等级配置模型
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class LevelConfig {
private Integer level;
private String levelName;
private Integer minPoints;
private Integer maxPoints;
private List<String> privileges;
private Double discountRate;
}

4. 积分服务

4.1 积分服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
/**
* 积分服务
*/
@Service
public class PointsService {

private final PointsMallProperties properties;
private final UserPointsRepository userPointsRepository;
private final PointsRecordRepository pointsRecordRepository;

public PointsService(PointsMallProperties properties) {
this.properties = properties;
this.userPointsRepository = null; // 注入
this.pointsRecordRepository = null; // 注入
}

/**
* 获取用户积分
* @param userId 用户ID
* @return 用户积分
*/
public UserPoints getUserPoints(Long userId) {
try {
UserPoints userPoints = userPointsRepository.findByUserId(userId);
if (userPoints == null) {
// 初始化用户积分
userPoints = initializeUserPoints(userId);
}
return userPoints;
} catch (Exception e) {
log.error("获取用户积分失败: userId={}", userId, e);
return null;
}
}

/**
* 增加积分
* @param userId 用户ID
* @param points 积分数量
* @param source 积分来源
* @param description 描述
* @return 操作结果
*/
public boolean addPoints(Long userId, Integer points, String source, String description) {
try {
// 1. 获取用户积分
UserPoints userPoints = getUserPoints(userId);
if (userPoints == null) {
return false;
}

// 2. 检查积分限制
if (!checkPointsLimit(userId, points, source)) {
return false;
}

// 3. 更新积分
userPoints.setTotalPoints(userPoints.getTotalPoints() + points);
userPoints.setAvailablePoints(userPoints.getAvailablePoints() + points);
userPoints.setUpdateTime(LocalDateTime.now());

// 4. 检查等级提升
checkLevelUp(userPoints);

// 5. 保存积分记录
savePointsRecord(userId, points, "EARN", source, description);

// 6. 保存用户积分
userPointsRepository.save(userPoints);

log.info("用户积分增加成功: userId={}, points={}, source={}", userId, points, source);

return true;

} catch (Exception e) {
log.error("增加积分失败: userId={}, points={}", userId, points, e);
return false;
}
}

/**
* 消费积分
* @param userId 用户ID
* @param points 积分数量
* @param source 消费来源
* @param description 描述
* @return 操作结果
*/
public boolean spendPoints(Long userId, Integer points, String source, String description) {
try {
// 1. 获取用户积分
UserPoints userPoints = getUserPoints(userId);
if (userPoints == null) {
return false;
}

// 2. 检查积分余额
if (userPoints.getAvailablePoints() < points) {
log.warn("用户积分余额不足: userId={}, available={}, required={}",
userId, userPoints.getAvailablePoints(), points);
return false;
}

// 3. 更新积分
userPoints.setAvailablePoints(userPoints.getAvailablePoints() - points);
userPoints.setUsedPoints(userPoints.getUsedPoints() + points);
userPoints.setUpdateTime(LocalDateTime.now());

// 4. 保存积分记录
savePointsRecord(userId, -points, "SPEND", source, description);

// 5. 保存用户积分
userPointsRepository.save(userPoints);

log.info("用户积分消费成功: userId={}, points={}, source={}", userId, points, source);

return true;

} catch (Exception e) {
log.error("消费积分失败: userId={}, points={}", userId, points, e);
return false;
}
}

/**
* 初始化用户积分
* @param userId 用户ID
* @return 用户积分
*/
private UserPoints initializeUserPoints(Long userId) {
UserPoints userPoints = UserPoints.builder()
.userId(userId)
.totalPoints(0)
.availablePoints(0)
.usedPoints(0)
.level(properties.getDefaultLevel())
.createTime(LocalDateTime.now())
.updateTime(LocalDateTime.now())
.build();

return userPointsRepository.save(userPoints);
}

/**
* 检查积分限制
* @param userId 用户ID
* @param points 积分数量
* @param source 积分来源
* @return 是否允许
*/
private boolean checkPointsLimit(Long userId, Integer points, String source) {
// 检查每日积分限制
if (points > properties.getMaxPointsPerDay()) {
log.warn("积分数量超过每日限制: userId={}, points={}", userId, points);
return false;
}

// 检查每月积分限制
LocalDateTime startOfMonth = LocalDateTime.now().withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0);
Integer monthlyPoints = pointsRecordRepository.getMonthlyPoints(userId, startOfMonth);
if (monthlyPoints != null && monthlyPoints + points > properties.getMaxPointsPerMonth()) {
log.warn("积分数量超过每月限制: userId={}, monthly={}, points={}", userId, monthlyPoints, points);
return false;
}

return true;
}

/**
* 检查等级提升
* @param userPoints 用户积分
*/
private void checkLevelUp(UserPoints userPoints) {
int newLevel = calculateLevel(userPoints.getTotalPoints());
if (newLevel > userPoints.getLevel()) {
userPoints.setLevel(newLevel);

// 等级提升奖励
if (properties.isEnableLevelUpReward()) {
addPoints(userPoints.getUserId(), properties.getLevelUpRewardPoints(),
"LEVEL_UP", "等级提升奖励");
}

log.info("用户等级提升: userId={}, oldLevel={}, newLevel={}",
userPoints.getUserId(), userPoints.getLevel(), newLevel);
}
}

/**
* 计算用户等级
* @param totalPoints 总积分
* @return 等级
*/
private int calculateLevel(Integer totalPoints) {
return Math.min(properties.getMaxLevel(),
totalPoints / properties.getPointsPerLevel() + 1);
}

/**
* 保存积分记录
* @param userId 用户ID
* @param points 积分数量
* @param type 类型
* @param source 来源
* @param description 描述
*/
private void savePointsRecord(Long userId, Integer points, String type,
String source, String description) {
PointsRecord record = PointsRecord.builder()
.userId(userId)
.points(points)
.type(type)
.source(source)
.description(description)
.createTime(LocalDateTime.now())
.build();

pointsRecordRepository.save(record);
}
}

5. 商城服务

5.1 商城服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
/**
* 商城服务
*/
@Service
public class MallService {

private final PointsMallProperties properties;
private final MallProductRepository productRepository;
private final ExchangeOrderRepository orderRepository;

public MallService(PointsMallProperties properties) {
this.properties = properties;
this.productRepository = null; // 注入
this.orderRepository = null; // 注入
}

/**
* 获取商品列表
* @param category 分类
* @param page 页码
* @param size 大小
* @return 商品列表
*/
public Page<MallProduct> getProducts(String category, int page, int size) {
try {
Pageable pageable = PageRequest.of(page, size, Sort.by("sortOrder").ascending());

if (category != null && !category.isEmpty()) {
return productRepository.findByCategoryAndStatus(category, "ACTIVE", pageable);
} else {
return productRepository.findByStatus("ACTIVE", pageable);
}

} catch (Exception e) {
log.error("获取商品列表失败: category={}", category, e);
return Page.empty();
}
}

/**
* 获取商品详情
* @param productId 商品ID
* @return 商品详情
*/
public MallProduct getProduct(Long productId) {
try {
return productRepository.findById(productId).orElse(null);
} catch (Exception e) {
log.error("获取商品详情失败: productId={}", productId, e);
return null;
}
}

/**
* 搜索商品
* @param keyword 关键词
* @param page 页码
* @param size 大小
* @return 搜索结果
*/
public Page<MallProduct> searchProducts(String keyword, int page, int size) {
try {
Pageable pageable = PageRequest.of(page, size, Sort.by("sortOrder").ascending());
return productRepository.findByNameContainingAndStatus(keyword, "ACTIVE", pageable);
} catch (Exception e) {
log.error("搜索商品失败: keyword={}", keyword, e);
return Page.empty();
}
}

/**
* 兑换商品
* @param userId 用户ID
* @param productId 商品ID
* @param quantity 数量
* @param shippingAddress 收货地址
* @param contactPhone 联系电话
* @return 兑换结果
*/
public ExchangeResult exchangeProduct(Long userId, Long productId, Integer quantity,
String shippingAddress, String contactPhone) {
try {
// 1. 获取商品信息
MallProduct product = getProduct(productId);
if (product == null) {
return ExchangeResult.builder()
.success(false)
.message("商品不存在")
.build();
}

// 2. 检查商品状态
if (!"ACTIVE".equals(product.getStatus())) {
return ExchangeResult.builder()
.success(false)
.message("商品已下架")
.build();
}

// 3. 检查库存
if (product.getStock() < quantity) {
return ExchangeResult.builder()
.success(false)
.message("库存不足")
.build();
}

// 4. 计算所需积分
Integer totalPoints = product.getPointsPrice() * quantity;

// 5. 检查用户积分
UserPoints userPoints = pointsService.getUserPoints(userId);
if (userPoints == null || userPoints.getAvailablePoints() < totalPoints) {
return ExchangeResult.builder()
.success(false)
.message("积分不足")
.build();
}

// 6. 检查兑换限制
if (!checkExchangeLimit(userId, quantity)) {
return ExchangeResult.builder()
.success(false)
.message("超过兑换限制")
.build();
}

// 7. 创建兑换订单
ExchangeOrder order = createExchangeOrder(userId, product, quantity,
totalPoints, shippingAddress, contactPhone);

// 8. 扣减积分
boolean spendSuccess = pointsService.spendPoints(userId, totalPoints,
"EXCHANGE", "兑换商品: " + product.getName());

if (!spendSuccess) {
return ExchangeResult.builder()
.success(false)
.message("积分扣减失败")
.build();
}

// 9. 扣减库存
product.setStock(product.getStock() - quantity);
productRepository.save(product);

// 10. 保存订单
orderRepository.save(order);

return ExchangeResult.builder()
.success(true)
.orderId(order.getId())
.orderNo(order.getOrderNo())
.message("兑换成功")
.build();

} catch (Exception e) {
log.error("兑换商品失败: userId={}, productId={}", userId, productId, e);

return ExchangeResult.builder()
.success(false)
.message("兑换失败: " + e.getMessage())
.build();
}
}

/**
* 检查兑换限制
* @param userId 用户ID
* @param quantity 数量
* @return 是否允许
*/
private boolean checkExchangeLimit(Long userId, Integer quantity) {
// 检查每日兑换限制
LocalDateTime startOfDay = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0);
Integer dailyExchanges = orderRepository.getDailyExchanges(userId, startOfDay);
if (dailyExchanges != null && dailyExchanges + quantity > properties.getMaxExchangePerDay()) {
return false;
}

// 检查每月兑换限制
LocalDateTime startOfMonth = LocalDateTime.now().withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0);
Integer monthlyExchanges = orderRepository.getMonthlyExchanges(userId, startOfMonth);
if (monthlyExchanges != null && monthlyExchanges + quantity > properties.getMaxExchangePerMonth()) {
return false;
}

return true;
}

/**
* 创建兑换订单
* @param userId 用户ID
* @param product 商品
* @param quantity 数量
* @param totalPoints 总积分
* @param shippingAddress 收货地址
* @param contactPhone 联系电话
* @return 兑换订单
*/
private ExchangeOrder createExchangeOrder(Long userId, MallProduct product, Integer quantity,
Integer totalPoints, String shippingAddress, String contactPhone) {
String orderNo = generateOrderNo();

return ExchangeOrder.builder()
.orderNo(orderNo)
.userId(userId)
.productId(product.getId())
.productName(product.getName())
.pointsPrice(product.getPointsPrice())
.quantity(quantity)
.totalPoints(totalPoints)
.status("PENDING")
.shippingAddress(shippingAddress)
.contactPhone(contactPhone)
.createTime(LocalDateTime.now())
.updateTime(LocalDateTime.now())
.build();
}

/**
* 生成订单号
* @return 订单号
*/
private String generateOrderNo() {
return "EX" + System.currentTimeMillis() + RandomUtils.nextInt(1000, 9999);
}
}

/**
* 兑换结果模型
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ExchangeResult {
private boolean success;
private Long orderId;
private String orderNo;
private String message;
private LocalDateTime exchangeTime;
}

6. 积分商城控制器

6.1 积分商城控制器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/**
* 积分商城控制器
*/
@RestController
@RequestMapping("/points-mall")
public class PointsMallController {

@Autowired
private PointsService pointsService;

@Autowired
private MallService mallService;

/**
* 获取用户积分
*/
@GetMapping("/points/{userId}")
public ResponseEntity<Map<String, Object>> getUserPoints(@PathVariable Long userId) {
try {
UserPoints userPoints = pointsService.getUserPoints(userId);

Map<String, Object> response = new HashMap<>();
response.put("success", userPoints != null);
response.put("userPoints", userPoints);

return ResponseEntity.ok(response);

} catch (Exception e) {
log.error("获取用户积分失败: userId={}", userId, e);

Map<String, Object> response = new HashMap<>();
response.put("success", false);
response.put("message", "获取积分失败: " + e.getMessage());

return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}
}

/**
* 获取商品列表
*/
@GetMapping("/products")
public ResponseEntity<Map<String, Object>> getProducts(
@RequestParam(required = false) String category,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "20") int size) {
try {
Page<MallProduct> products = mallService.getProducts(category, page, size);

Map<String, Object> response = new HashMap<>();
response.put("success", true);
response.put("products", products.getContent());
response.put("total", products.getTotalElements());
response.put("page", page);
response.put("size", size);

return ResponseEntity.ok(response);

} catch (Exception e) {
log.error("获取商品列表失败", e);

Map<String, Object> response = new HashMap<>();
response.put("success", false);
response.put("message", "获取商品列表失败: " + e.getMessage());

return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}
}

/**
* 兑换商品
*/
@PostMapping("/exchange")
public ResponseEntity<Map<String, Object>> exchangeProduct(@RequestBody ExchangeRequest request) {
try {
ExchangeResult result = mallService.exchangeProduct(
request.getUserId(),
request.getProductId(),
request.getQuantity(),
request.getShippingAddress(),
request.getContactPhone()
);

Map<String, Object> response = new HashMap<>();
response.put("success", result.isSuccess());
response.put("orderId", result.getOrderId());
response.put("orderNo", result.getOrderNo());
response.put("message", result.getMessage());

return ResponseEntity.ok(response);

} catch (Exception e) {
log.error("兑换商品失败", e);

Map<String, Object> response = new HashMap<>();
response.put("success", false);
response.put("message", "兑换失败: " + e.getMessage());

return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}
}
}

/**
* 兑换请求模型
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ExchangeRequest {
private Long userId;
private Long productId;
private Integer quantity;
private String shippingAddress;
private String contactPhone;
}

7. 总结

通过积分商城的实现,我们成功构建了一个完整的积分系统和商城平台。关键特性包括:

7.1 核心优势

  1. 积分系统: 积分获取、消费、管理
  2. 商城功能: 商品展示、分类、搜索
  3. 积分兑换: 积分兑换商品、服务
  4. 订单管理: 兑换订单处理、状态跟踪
  5. 用户权益: 会员等级、特权管理

7.2 最佳实践

  1. 积分管理: 完善的积分获取和消费机制
  2. 商城运营: 灵活的商品管理和展示
  3. 兑换流程: 可靠的兑换流程和订单管理
  4. 用户权益: 等级制度和特权管理
  5. 系统监控: 全面的监控和数据分析

这套积分商城方案不仅能够提供完整的积分系统,还包含了商城功能、兑换管理、用户权益等核心功能,是现代电商平台的重要组件。