16 KiB
16 KiB
积分充值系统使用指南
📋 功能概述
本系统实现了完整的积分直接购买功能,用户可以通过支付宝/微信支付直接购买积分,无需依赖礼品码。
✨ 核心特性
- ✅ 多套餐选择:支持不同价格和数量的积分套餐
- ✅ 首充奖励:首次充值额外赠送10%积分
- ✅ 赠送积分:每个套餐可配置赠送积分
- ✅ 支付方式:支持支付宝和微信支付
- ✅ 充值记录:完整的充值历史记录
- ✅ 自动到账:支付成功后自动充值到账
- ✅ 积分有效期:可配置积分有效期(默认365天)
🗂️ 数据库结构
新增表
1. points_package - 积分套餐表
CREATE TABLE `points_package` (
`id` bigint PRIMARY KEY AUTO_INCREMENT,
`name` varchar(64) NOT NULL COMMENT '套餐名称',
`points` int NOT NULL COMMENT '基础积分',
`bonus_points` int DEFAULT 0 COMMENT '赠送积分',
`total_points` int NOT NULL COMMENT '总积分',
`price` decimal(10,2) NOT NULL COMMENT '价格',
`original_price` decimal(10,2) COMMENT '原价',
`points_expire_days` int DEFAULT 365 COMMENT '有效期',
`discount_label` varchar(32) COMMENT '优惠标签',
`is_hot` tinyint(1) DEFAULT 0 COMMENT '是否热门',
`is_active` tinyint(1) DEFAULT 1 COMMENT '是否上架'
);
默认数据:
| 套餐名称 | 积分 | 赠送 | 总计 | 价格 | 原价 |
|---|---|---|---|---|---|
| 体验包 | 100 | 0 | 100 | ¥10 | - |
| 标准包 | 500 | 50 | 550 | ¥48 | ¥50 |
| 超值包 | 1000 | 150 | 1150 | ¥88 | ¥100 |
| 豪华包 | 3000 | 500 | 3500 | ¥258 | ¥300 |
| 至尊包 | 5000 | 1000 | 6000 | ¥398 | ¥500 |
| 旗舰包 | 10000 | 3000 | 13000 | ¥688 | ¥1000 |
扩展表
2. order 表扩展
新增字段:
ALTER TABLE `order`
ADD COLUMN `order_type` tinyint DEFAULT 1 COMMENT '1-会员订单/2-积分订单',
ADD COLUMN `points_package_id` bigint COMMENT '积分套餐ID',
ADD COLUMN `points_amount` int COMMENT '积分数量';
🔌 API接口文档
用户端接口(/user/points)
1. 获取积分套餐列表
接口:GET /user/points/packages
权限:公开访问(无需登录)
响应示例:
{
"code": 200,
"message": "成功",
"data": [
{
"id": 2,
"name": "标准包",
"description": "日常使用推荐",
"points": 500,
"bonusPoints": 50,
"totalPoints": 550,
"price": 48.00,
"originalPrice": 50.00,
"pointsExpireDays": 365,
"discountLabel": "赠送50积分",
"isHot": true,
"isActive": true
}
]
}
2. 获取热门套餐
接口:GET /user/points/packages/hot?limit=3
权限:公开访问
参数:
limit:数量限制,默认3
3. 创建充值订单 ⭐
接口:POST /user/points/recharge
权限:需要登录
请求体:
{
"packageId": 2,
"paymentMethod": 2
}
参数说明:
packageId:套餐ID(必填)paymentMethod:支付方式(必填)1= 支付宝2= 微信支付
响应示例:
{
"code": 200,
"message": "成功",
"data": {
"orderNo": "ORD20251021123456",
"amount": 48.00,
"pointsAmount": 605,
"paymentMethod": 2,
"paymentParams": "{\"prepay_id\":\"wx2025102112345678\"}",
"createTime": "2025-10-21T12:34:56"
}
}
注意:
- 首次充值会额外赠送10%积分
pointsAmount= 基础积分 + 赠送积分 + 首充奖励(如果是首次)paymentParams需要传给前端调起支付
4. 获取充值记录
接口:GET /user/points/recharge/records?page=1&size=10
权限:需要登录
响应示例:
{
"code": 200,
"message": "成功",
"data": [
{
"orderNo": "ORD20251021123456",
"packageName": "标准包",
"pointsAmount": 605,
"amount": 48.00,
"paymentMethodName": "微信支付",
"statusName": "已完成",
"createTime": "2025-10-21T12:34:56",
"paidAt": "2025-10-21T12:35:10"
}
]
}
5. 获取充值统计
接口:GET /user/points/recharge/stats
权限:需要登录
响应示例:
{
"code": 200,
"message": "成功",
"data": {
"totalRechargeCount": 5,
"totalAmount": 240.00,
"totalPoints": 3025,
"isFirstRecharge": false,
"lastRechargeTime": "2025-10-21T12:35:10"
}
}
支付回调接口(/payment/callback)
1. 支付宝回调
接口:POST /payment/callback/alipay
权限:公开访问(支付宝服务器调用)
处理流程:
- 验证支付宝签名
- 检查交易状态(
TRADE_SUCCESS或TRADE_FINISHED) - 调用充值处理逻辑
- 返回
success给支付宝
2. 微信支付回调
接口:POST /payment/callback/wechat
权限:公开访问(微信服务器调用)
处理流程:
- 解析XML数据
- 验证微信签名
- 检查支付结果
- 调用充值处理逻辑
- 返回XML响应给微信
3. 测试回调(仅开发环境)
接口:POST /payment/callback/test?orderNo=ORD20251021123456
权限:公开访问
用途:在没有真实支付的情况下测试充值流程
示例:
curl -X POST "http://localhost:8080/payment/callback/test?orderNo=ORD20251021123456"
🔄 业务流程
完整充值流程
用户端 后端 支付平台
| | |
| 1. 浏览套餐列表 | |
|------------------------>| |
| GET /packages | |
|<------------------------| |
| | |
| 2. 创建充值订单 | |
|------------------------>| |
| POST /recharge | |
| {packageId: 2} | |
| | 3. 生成订单 |
| | 4. 生成支付参数 |
|<------------------------| |
| {orderNo, paymentParams} |
| | |
| 5. 调起支付 | |
|-------------------------------------------------->|
| | |
| | 6. 支付成功 |
| |<---------------------------|
| | POST /callback/alipay |
| | |
| | 7. 验证签名 |
| | 8. 增加用户积分 |
| | 9. 更新订单状态 |
| | 10. 记录变动日志 |
| |-------------------------->|
| | 返回 "success" |
| | |
| 11. 查询充值记录 | |
|------------------------>| |
|<------------------------| |
💻 前端集成示例
1. 获取套餐列表
// 获取积分套餐
async function getPackages() {
const response = await fetch('/user/points/packages');
const result = await response.json();
if (result.code === 200) {
displayPackages(result.data);
}
}
2. 创建充值订单
// 创建充值订单
async function recharge(packageId, paymentMethod) {
const response = await fetch('/user/points/recharge', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + getToken()
},
body: JSON.stringify({
packageId: packageId,
paymentMethod: paymentMethod // 1=支付宝, 2=微信
})
});
const result = await response.json();
if (result.code === 200) {
const { orderNo, paymentParams } = result.data;
// 调起支付
if (paymentMethod === 1) {
// 支付宝支付
alipay(paymentParams);
} else {
// 微信支付
wechatPay(paymentParams);
}
}
}
3. 支付宝支付(示例)
function alipay(paymentParams) {
// 创建表单并提交
const form = document.createElement('form');
form.action = 'https://openapi.alipay.com/gateway.do';
form.method = 'POST';
form.innerHTML = paymentParams; // 支付宝SDK生成的表单
document.body.appendChild(form);
form.submit();
}
4. 微信支付(示例)
function wechatPay(paymentParams) {
const params = JSON.parse(paymentParams);
// 调起微信支付
WeixinJSBridge.invoke('getBrandWCPayRequest', {
appId: params.appId,
timeStamp: params.timeStamp,
nonceStr: params.nonceStr,
package: params.package,
signType: params.signType,
paySign: params.paySign
}, function(res) {
if (res.err_msg === 'get_brand_wcpay_request:ok') {
// 支付成功,跳转到充值记录页面
window.location.href = '/points/records';
}
});
}
🔧 后端开发说明
1. 支付接口对接
目前 generatePaymentParams() 方法返回的是模拟数据,需要对接真实的支付宝/微信SDK:
支付宝SDK集成
<!-- pom.xml -->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.38.0.ALL</version>
</dependency>
// 生成支付宝支付参数
private String generateAlipayParams(Order order) {
AlipayClient alipayClient = new DefaultAlipayClient(
"https://openapi.alipay.com/gateway.do",
APP_ID,
PRIVATE_KEY,
"json",
"UTF-8",
ALIPAY_PUBLIC_KEY,
"RSA2"
);
AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
request.setNotifyUrl("https://yourdomain.com/payment/callback/alipay");
JSONObject bizContent = new JSONObject();
bizContent.put("out_trade_no", order.getOrderNo());
bizContent.put("total_amount", order.getAmount());
bizContent.put("subject", "积分充值");
bizContent.put("product_code", "QUICK_MSECURITY_PAY");
request.setBizContent(bizContent.toString());
AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
return response.getBody();
}
微信支付SDK集成
<!-- pom.xml -->
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-java</artifactId>
<version>0.2.12</version>
</dependency>
// 生成微信支付参数
private String generateWechatPayParams(Order order) {
// 使用微信支付SDK创建预支付订单
// 返回prepay_id等参数
}
2. 回调签名验证
支付宝签名验证
@PostMapping("/alipay")
public String alipayCallback(HttpServletRequest request) {
Map<String, String> params = new HashMap<>();
Map<String, String[]> requestParams = request.getParameterMap();
for (String name : requestParams.keySet()) {
params.put(name, request.getParameter(name));
}
// 验证签名
boolean signVerified = AlipaySignature.rsaCheckV1(
params,
ALIPAY_PUBLIC_KEY,
"UTF-8",
"RSA2"
);
if (!signVerified) {
return "fail";
}
// 验证通过,处理业务
String orderNo = params.get("out_trade_no");
String tradeStatus = params.get("trade_status");
if ("TRADE_SUCCESS".equals(tradeStatus)) {
pointsRechargeService.handleRechargePaymentSuccess(orderNo);
}
return "success";
}
微信支付签名验证
@PostMapping("/wechat")
public String wechatCallback(@RequestBody String xmlData) {
// 解析XML
Map<String, String> params = WXPayUtil.xmlToMap(xmlData);
// 验证签名
boolean signVerified = WXPayUtil.isSignatureValid(
params,
WECHAT_API_KEY
);
if (!signVerified) {
return errorXml();
}
// 验证通过,处理业务
String orderNo = params.get("out_trade_no");
String resultCode = params.get("result_code");
if ("SUCCESS".equals(resultCode)) {
pointsRechargeService.handleRechargePaymentSuccess(orderNo);
}
return successXml();
}
📊 数据库迁移
执行迁移脚本
# 1. 备份数据库
mysqldump -u root -p 1818ai > backup_$(date +%Y%m%d).sql
# 2. 执行V6迁移脚本
mysql -u root -p 1818ai < V6__add_points_recharge_system.sql
# 3. 验证结果
mysql -u root -p 1818ai -e "SELECT * FROM points_package;"
mysql -u root -p 1818ai -e "DESC \`order\`;"
🧪 测试流程
1. 开发环境测试
# 1. 获取套餐列表
curl -X GET "http://localhost:8080/user/points/packages"
# 2. 创建充值订单(需要登录token)
curl -X POST "http://localhost:8080/user/points/recharge" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"packageId":2,"paymentMethod":2}'
# 3. 模拟支付成功(测试用)
curl -X POST "http://localhost:8080/payment/callback/test?orderNo=ORD20251021123456"
# 4. 查看充值记录
curl -X GET "http://localhost:8080/user/points/recharge/records?page=1&size=10" \
-H "Authorization: Bearer YOUR_TOKEN"
# 5. 查看用户积分
curl -X GET "http://localhost:8080/user/info" \
-H "Authorization: Bearer YOUR_TOKEN"
2. 生产环境验证
- ✅ 确认支付宝/微信支付配置正确
- ✅ 确认回调URL可以被外网访问
- ✅ 小额充值测试(¥0.01)
- ✅ 验证积分到账是否正确
- ✅ 验证首充奖励是否生效
- ✅ 验证充值记录是否正确
🛡️ 安全配置
SecurityConfig 配置说明
// 公开接口(无需登录)
"/user/points/packages/**" // 套餐浏览
"/payment/callback/**" // 支付回调
// 需要登录的接口
"/user/points/recharge" // 创建充值订单
"/user/points/recharge/**" // 充值记录、统计
📈 运营建议
1. 套餐定价策略
- 体验包:吸引新用户尝试
- 标准包:日常充值主力
- 超值包:性价比标杆,设置为热门
- 豪华包/至尊包:满足重度用户
- 旗舰包:年度大额充值,最高性价比
2. 营销活动
- 首充奖励:已自动实现,首次充值额外赠送10%
- 限时优惠:通过
discount_label标签展示 - 热门推荐:将主推套餐设置为
is_hot=1 - 节日活动:临时调整
bonus_points赠送比例
3. 数据分析
查看充值统计视图:
SELECT * FROM v_points_recharge_stats
ORDER BY recharge_date DESC
LIMIT 30;
❓ 常见问题
Q1: 支付成功但积分没到账?
检查步骤:
- 查看订单状态:
SELECT * FROM order WHERE order_no = 'xxx'; - 查看支付回调日志:检查
/payment/callback/alipay日志 - 查看用户积分:
SELECT points FROM user WHERE id = xxx; - 查看积分变动日志:
SELECT * FROM points_consumption_log WHERE user_id = xxx;
手动补单:
curl -X POST "http://localhost:8080/payment/callback/test?orderNo=xxx"
Q2: 如何修改套餐价格?
UPDATE points_package
SET price = 45.00,
update_time = NOW()
WHERE id = 2;
Q3: 如何下架某个套餐?
UPDATE points_package
SET is_active = 0,
update_time = NOW()
WHERE id = 6;
Q4: 如何查看用户充值历史?
SELECT
o.order_no,
o.amount,
o.points_amount,
pp.name as package_name,
o.create_time,
o.paid_at,
CASE o.status
WHEN 0 THEN '待支付'
WHEN 1 THEN '已完成'
WHEN 2 THEN '已取消'
WHEN 3 THEN '支付失败'
END as status_name
FROM `order` o
LEFT JOIN points_package pp ON o.points_package_id = pp.id
WHERE o.user_id = 123
AND o.order_type = 2
ORDER BY o.create_time DESC;
🎯 总结
✅ 功能完整:支持套餐管理、订单创建、支付回调、充值到账全流程
✅ 安全可靠:JWT认证、订单防重、支付签名验证
✅ 易于扩展:支持新增支付方式、调整套餐策略
✅ 数据完整:充值记录、变动日志、统计分析
现在用户可以直接购买积分,不再依赖礼品码!🎉