java实现会员充值功能

近期负责的项目中有关于充值会员的功能,特做一个会员充值流程小结,这中间或许也存在着不足。希望可以得到大家的理解和建议。在调用第三方接口支付时修改表的状态(此处不做详细阐述)。

业务分析:

如下图,用户可以选择想要开通的会员等级(初级、中级、高级、超级),不同等级有不同的开通时长选择(一个月、一个季度、半年、一年),每个等级的会员对应的权限不一致,用户可以随意选择。

在这里插入图片描述

思路介绍:
在购买VIP成功后,要判断该用户当前是否为会员:

场景一:用户之前没有充值过会员,或者已经过期,就根据当前系统时间,增加对应充值时长。
场景二:用户目前是会员状态; 会员状态下还有三种场景:
    1.充值比当前会员等级低的会员; 例如:当前用户已经是超级会员,但是又充值了初级会员
    2.充值比当前会员等级高的会员;例如:当前用户已经是初级会员,但是又充值了超级会员
    3.充值与当前会员等级一样的会员;例如:当前用户已经是中级会员,又充值了中级会员

算法思路:

模拟会员价格表: 单位为分比较好计算

等级半年全年价格单位
初级会员6001500250015500
中级会员7001600260015600
高级会员8001700270015700
超级会员9001800280015800

月标准都按31天计算

场景

初级 升 超级:

1.先算出初级还剩多少天 :公式:到期时间-当前时间=相差时间 ,如果低于一天直接按一天算
2.算出初级每天多少钱: 公式:原来开通方式的价格/ 套餐天数=每天价格  
3.初级剩余天数换算成钱还剩多少钱:公式:剩余天数*每天价格 =剩余金额
4.计算超级会员每天价格:  公式:开通方式价格/套餐时长=每天价格
5.初级换算的钱可以买几天超级:剩余金额/超级会员每天价格 =换n天 
最终:超级会员套餐时长+换n天=超级会员到期时间

超级 升初级:

1.算出超级每天价格:公式: 开通方式价格/套餐时长=超级会员每天价格
2.算出初级会员的钱可以买几天超级会员:公式:初级会员开通方式价格/初级会员每天价格=换n天
最终:到期时间+换n天=超级会员到期时间

中间 升 中级:

到期时间+中间套餐时间=中级会员到期时间

代码实现

表结构:

会员规则表:

在这里插入图片描述

用户表:

在这里插入图片描述

请求实体:

@Data
public class PayMember {
    // 充值对象
    private Long userId;
    // 商户ID
    private Long dealerId;
    // 会员[1:初级;2:中级;3:高级;4:超级]
    private Byte memberType;
    // 购买的套餐[0:月;1:季度;2:半年;3:全年;]
    private Byte comboId;
}

业务代码:

@Override
public ResultUtils payMember(PayMember payMember) {
    // combosMap的SQL:
    //        SELECT `month`,
    //               season,
    //               semester,
    //               yearly,
    //               type
    //        FROM dealer_member_rule
    //        WHERE dealer_id = #{dealerId}
    Map<Integer, Object> combosMap = dealerMemberRuleMapper.selectCombos(payMember.getDealerId());
    // 查询当前用户会员情况
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("user_id", payMember.getUserId())
            .select("member_type", "membership_due","member_pay");
    User user = userMapper.selectOne(queryWrapper);
    UpdateWrapper<User> wrapper = new UpdateWrapper<>();
    // 判断会员情况
    if (ObjectUtil.isEmpty(user.getMembershipDue()) || LocalDateTime.now().isAfter(user.getMembershipDue())) {//第一次开通会员|| 会员已经到期
        // 非升级续费,第一次开通 || 到期后开通
        wrapper.eq("user_id", payMember.getUserId())
                .set("member_pay", payMember.getComboId())
                .set("membership_due", LocalDateTime.now().plusMonths(combo(payMember.getComboId())))
                .set("member_type", payMember.getMemberType());
    } else { // 续费 || 升级
        if (user.getMemberType() > payMember.getMemberType()) {// 购买了比当前低级的套餐 (当前超级升初级)
            // 获取当前使用的套餐  旧套餐
            Map<String, Object> oldCombo = (Map<String, Object>) combosMap.get(user.getMemberType().intValue());
            // 得出上传开通旧套餐的时长名字
            String timeName = comboName(user.getMemberPay());
            Integer oldPrice = (Integer) oldCombo.get(timeName);// 得出旧套餐的价格
            // totalDays=这个套餐有多少天
            int totalDays = combo(user.getMemberPay()) * 31;// 套餐总天数=n月*标准天数(31)
            // 每天价格=套餐价格/总天数
            int oldEveryDayThePrice = oldPrice / totalDays;
            // 算出新套餐可以买几天旧套餐
            // 即将要买的套餐 新套餐
            Map<String, Object> newCombo = (Map<String, Object>) combosMap.get(payMember.getMemberType().intValue());
            Integer newPrice = (Integer) newCombo.get(comboName(payMember.getComboId()));// 新套餐价格
            // 可以买几天旧套餐=新套餐价格/旧套餐每天价格
            int day = newPrice / oldEveryDayThePrice;
            if (day<0) day = 1;// 少用一天送一天
            // 会员到期时间=当前时间+新套餐天数+旧套餐这算天数
            //到期时间加上最终天数
            wrapper.eq("user_id", payMember.getUserId())
                    .set("member_pay", user.getMemberPay())// 还是就套餐的时长
                    .set("membership_due", user.getMembershipDue().plusDays(day))//到期时间加最终天数
                    .set("member_type", user.getMemberType());
        } else if (user.getMemberType() == payMember.getMemberType()) {// 购买了和当前一样的套餐
            //一样的套餐直接加上对应的天数
            wrapper.eq("user_id", payMember.getUserId())
                    .set("member_pay", user.getMemberPay())// 还是就套餐的时长
                    .set("membership_due", user.getMembershipDue().plusMonths(combo(payMember.getComboId())))//到期时间加最终天数
                    .set("member_type", user.getMemberType());
        } else {// 购买的比当前高级的套餐
            // 算法和 高买低相反
            // 初级还剩余几天
            Duration duration = Duration.between(LocalDateTime.now(), user.getMembershipDue());//到期时间和当前时间的差
            long hours = duration.toHours();//相差的小时数
            long residueDay = hours / 24L;//旧套餐剩余天数
            if (residueDay < 1) residueDay = 1; // 小于一天就送一天

            // 旧套餐每天价格=原来开通方式的价格/套餐天数
            // 获取当前使用的套餐  旧套餐
            Map<String, Object> oldCombo = (Map<String, Object>) combosMap.get(user.getMemberType().intValue());
            // 得出上传开通旧套餐的时长名字
            String timeName = comboName(user.getMemberPay());
            Integer oldPrice = (Integer) oldCombo.get(timeName);// 得出旧套餐的价格
            int totalDays = combo(user.getMemberPay()) * 31;// 套餐总天数=n月*标准天数(31)
            // 每天价格=套餐价格/总天数
            int oldEveryDayThePrice = oldPrice / totalDays;
            long residueMoney = residueDay * oldEveryDayThePrice;//剩余的钱=剩余天数*每天价格
            // 获取新套餐
            Map<String, Object> newCombo = (Map<String, Object>) combosMap.get(payMember.getMemberType().intValue());
            // 对应时长的套餐价格
            Integer newPrice = (Integer) newCombo.get(comboName(payMember.getComboId()));
            // 算出新套餐每天价格
            int daysMoney = newPrice / (combo(payMember.getComboId()) * 31);
            // 算出剩余的钱可以买几天新套餐  可购买天数=剩余的钱/新套餐每天价格
            long buyDaysNumber = residueMoney / daysMoney;
            if (buyDaysNumber < 1) {// 如果小于1天就直接送一天
                buyDaysNumber = 1;
            }
            // 最终到期时间=到期时间+((月*31)+旧套餐可以买的天数)
            LocalDateTime membership_due = user.getMembershipDue().plusDays((combo(payMember.getComboId()) * 31) + buyDaysNumber);
            wrapper.eq("user_id", payMember.getUserId())
                    .set("member_pay", payMember.getComboId())// 还是就套餐的时长
                    .set("membership_due", membership_due)//到期时间加最终天数
                    .set("member_type", payMember.getMemberType());
        }
    }
    int update = userMapper.update(new User(), wrapper);
    log.info("充值会员模块-用户ID:{},充值结果:{}", payMember.getUserId(), update > 0 ? "成功" : "失败");
    return ResultUtils.success();
}

/**
 * 套餐名称 方便取套餐值
 *
 * @param type [0:月;1:季度;2:半年;3:全年;]
 * @return
 */
private String comboName(Byte type) {
    switch (type) {
        case 0:
            return "month"; // 取月字段的价格
        case 1:
            return "season";// 取季字段的价格
        case 2:
            return "semester";// 半年
        case 3:
            return "yearly";// 一年
    }
    return null;
}
/**
 * 套餐时间
 *
 * @param type [0:月;1:季度;2:半年;3:全年;]
 * @return
 */
private Integer combo(Byte type) {
    switch (type) {
        case 0:
            return 1;// 一个月 1一个月
        case 1:
            return 3;// 一个季度 三个月
        case 2:
            return 6;// 半年 六个月
        case 3:
            return 12;// 一年 十二个月
    }
    return null;
}
  • 34
    点赞
  • 104
    收藏
    觉得还不错? 一键收藏
  • 20
    评论
### 回答1: 要开发一个带有会员充值会员有效期和会员等级的知识付费系统,可以使用Java语言实现。首先,需要设计数据库模型,包括会员信息、订单信息、支付信息等。然后,可以使用Spring框架来实现业务逻辑和控制器,使用MyBatis框架来实现数据访问层。在系统中,可以使用第三方支付平台来实现会员充值功能,同时可以使用定时任务来实现会员有效期的自动更新。根据会员等级的不同,可以设置不同的价格和折扣,以及不同的权限和服务。最后,需要进行系统测试和优化,确保系统的稳定性和性能。 ### 回答2: 要开发带有会员充值会员有效期和会员等级的知识付费系统,可以通过以下步骤使用Java实现: 1. 数据库设计:首先,设计数据库以存储用户信息、会员等级、会员充值记录和系统设置等数据。创建用户表、会员等级表、充值记录表等,并建立它们之间的关系。 2. 用户注册和登录功能实现用户注册和登录功能,包括验证用户输入的用户名和密码等信息,并将用户信息存储到数据库中。 3. 会员等级管理:设计会员等级表,并在注册成功或用户充值时根据充值金额或条件更新用户的会员等级。 4. 会员充值功能:提供会员充值接口,用户可以选择充值金额,并将充值记录插入到充值记录表中,同时更新用户的会员有效期和等级。 5. 会员有效期管理:在用户充值或注册成功后,根据系统设置的会员有效期规则更新用户的会员有效期。可以使用定时任务或其他方式,定期检查用户的会员有效期是否过期并更新其会员等级。 6. 付费知识购买:为用户提供付费知识购买接口,用户可以选择购买感兴趣的知识内容,并扣除相应的费用。 7. 系统后台管理:提供后台管理界面,允许管理员管理用户信息、会员等级、会员充值系统设置等功能,包括添加、删除、修改用户信息和等级设定等。 8. 安全性和验证:确保系统的安全性,例如使用加密算法对用户密码进行加密存储,对敏感操作进行权限验证等。 9. 界面设计和优化:设计用户友好的界面,使用户能够方便地进行充值、购买和管理。 10. 测试和部署:测试系统的各项功能是否正常,并根据需要进行优化和改进。最后,部署系统到服务器上,确保系统能够正常运行。 以上就是使用Java实现带有会员充值会员有效期和会员等级的知识付费系统的主要步骤。当然,系统的详细实现和具体功能还需根据具体需求进行具体设计和开发。
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值