# 积分充值系统使用指南 ## 📋 功能概述 本系统实现了完整的积分直接购买功能,用户可以通过支付宝/微信支付直接购买积分,无需依赖礼品码。 ### ✨ 核心特性 - ✅ **多套餐选择**:支持不同价格和数量的积分套餐 - ✅ **首充奖励**:首次充值额外赠送10%积分 - ✅ **赠送积分**:每个套餐可配置赠送积分 - ✅ **支付方式**:支持支付宝和微信支付 - ✅ **充值记录**:完整的充值历史记录 - ✅ **自动到账**:支付成功后自动充值到账 - ✅ **积分有效期**:可配置积分有效期(默认365天) --- ## 🗂️ 数据库结构 ### 新增表 #### 1. `points_package` - 积分套餐表 ```sql 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` 表扩展 新增字段: ```sql 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` **权限**:公开访问(无需登录) **响应示例**: ```json { "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` **权限**:需要登录 **请求体**: ```json { "packageId": 2, "paymentMethod": 2 } ``` **参数说明**: - `packageId`:套餐ID(必填) - `paymentMethod`:支付方式(必填) - `1` = 支付宝 - `2` = 微信支付 **响应示例**: ```json { "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` **权限**:需要登录 **响应示例**: ```json { "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` **权限**:需要登录 **响应示例**: ```json { "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` **权限**:公开访问(支付宝服务器调用) **处理流程**: 1. 验证支付宝签名 2. 检查交易状态(`TRADE_SUCCESS` 或 `TRADE_FINISHED`) 3. 调用充值处理逻辑 4. 返回 `success` 给支付宝 --- #### 2. 微信支付回调 **接口**:`POST /payment/callback/wechat` **权限**:公开访问(微信服务器调用) **处理流程**: 1. 解析XML数据 2. 验证微信签名 3. 检查支付结果 4. 调用充值处理逻辑 5. 返回XML响应给微信 --- #### 3. 测试回调(仅开发环境) **接口**:`POST /payment/callback/test?orderNo=ORD20251021123456` **权限**:公开访问 **用途**:在没有真实支付的情况下测试充值流程 **示例**: ```bash 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. 获取套餐列表 ```javascript // 获取积分套餐 async function getPackages() { const response = await fetch('/user/points/packages'); const result = await response.json(); if (result.code === 200) { displayPackages(result.data); } } ``` --- ### 2. 创建充值订单 ```javascript // 创建充值订单 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. 支付宝支付(示例) ```javascript 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. 微信支付(示例) ```javascript 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集成 ```xml com.alipay.sdk alipay-sdk-java 4.38.0.ALL ``` ```java // 生成支付宝支付参数 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集成 ```xml com.github.wechatpay-apiv3 wechatpay-java 0.2.12 ``` ```java // 生成微信支付参数 private String generateWechatPayParams(Order order) { // 使用微信支付SDK创建预支付订单 // 返回prepay_id等参数 } ``` --- ### 2. 回调签名验证 #### 支付宝签名验证 ```java @PostMapping("/alipay") public String alipayCallback(HttpServletRequest request) { Map params = new HashMap<>(); Map 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"; } ``` #### 微信支付签名验证 ```java @PostMapping("/wechat") public String wechatCallback(@RequestBody String xmlData) { // 解析XML Map 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(); } ``` --- ## 📊 数据库迁移 ### 执行迁移脚本 ```bash # 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. 开发环境测试 ```bash # 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. 生产环境验证 1. ✅ 确认支付宝/微信支付配置正确 2. ✅ 确认回调URL可以被外网访问 3. ✅ 小额充值测试(¥0.01) 4. ✅ 验证积分到账是否正确 5. ✅ 验证首充奖励是否生效 6. ✅ 验证充值记录是否正确 --- ## 🛡️ 安全配置 ### SecurityConfig 配置说明 ```java // 公开接口(无需登录) "/user/points/packages/**" // 套餐浏览 "/payment/callback/**" // 支付回调 // 需要登录的接口 "/user/points/recharge" // 创建充值订单 "/user/points/recharge/**" // 充值记录、统计 ``` --- ## 📈 运营建议 ### 1. 套餐定价策略 - **体验包**:吸引新用户尝试 - **标准包**:日常充值主力 - **超值包**:性价比标杆,设置为热门 - **豪华包/至尊包**:满足重度用户 - **旗舰包**:年度大额充值,最高性价比 ### 2. 营销活动 - **首充奖励**:已自动实现,首次充值额外赠送10% - **限时优惠**:通过 `discount_label` 标签展示 - **热门推荐**:将主推套餐设置为 `is_hot=1` - **节日活动**:临时调整 `bonus_points` 赠送比例 ### 3. 数据分析 查看充值统计视图: ```sql SELECT * FROM v_points_recharge_stats ORDER BY recharge_date DESC LIMIT 30; ``` --- ## ❓ 常见问题 ### Q1: 支付成功但积分没到账? **检查步骤**: 1. 查看订单状态:`SELECT * FROM order WHERE order_no = 'xxx';` 2. 查看支付回调日志:检查 `/payment/callback/alipay` 日志 3. 查看用户积分:`SELECT points FROM user WHERE id = xxx;` 4. 查看积分变动日志:`SELECT * FROM points_consumption_log WHERE user_id = xxx;` **手动补单**: ```bash curl -X POST "http://localhost:8080/payment/callback/test?orderNo=xxx" ``` --- ### Q2: 如何修改套餐价格? ```sql UPDATE points_package SET price = 45.00, update_time = NOW() WHERE id = 2; ``` --- ### Q3: 如何下架某个套餐? ```sql UPDATE points_package SET is_active = 0, update_time = NOW() WHERE id = 6; ``` --- ### Q4: 如何查看用户充值历史? ```sql 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认证、订单防重、支付签名验证 ✅ **易于扩展**:支持新增支付方式、调整套餐策略 ✅ **数据完整**:充值记录、变动日志、统计分析 现在用户可以直接购买积分,不再依赖礼品码!🎉