博客 / 詳情

返回

類支付寶積分系統設計方案(過期、兑獎)

個人博客:無奈何楊(wnhyang)

個人語雀:wnhyang

共享語雀:在線知識共享

Github:wnhyang - Overview


聲明

本篇文章純粹拋磚引玉!

需求説明

開門見山,業務背景直接跳過。

類比支付寶會員積分,支付寶APP-我的-支付寶會員。

支付寶會員-XXX積分-積分規則,可以看到具體的積分規則,本篇文章類比於此積分業務場景,做簡單的設計。

積分説明

積分不具有貨幣或現金價值,不可兑現,不可轉讓。用户可以通過支付、賬户服務、金融理財和積分獎勵活動等方式來獲取積分。

積分可以兑換各類權益、參與各種積分活動等,具體以權益兑換及活動頁面展示為準。

積分領取規則

積分發放後,用户可前往“我的”-“支付寶會員”,點擊領取積分球,或者在支付成功頁面、服務消息提醒、賬單點擊領取,積分方可到賬。積分自產生之時起,領取有效期7天(168小時),逾期不領則作廢,不予補發。

積分獲取方式

1、支付

2、賬户服務

3、金融理財

4、掃一掃

5、等

積分有效期

用户獲得的積分有效期為自獲得當月起的12個自然月,有效期內未使用的積分到期將自動清零,不予補發。

温馨提示:

1、用户日常使用的積分,將優先使用即將過期的積分。

2、每月,用户可在“我的”-“支付寶會員”-“收支/訂單/規則”頁查看當月月底即將過期的積分。

3、已使用的積分若發生退還,積分有效期不變,仍以該筆積分原獲取時間計算有效期。

積分權益兑換

積分可以兑換各類權益、參與各種積分活動等,具體以權益兑換及活動頁面展示為準。

積分與成長體系

需求分析

因為上面幾乎都是粘貼於支付寶對外展示的積分規則,而這篇文章涉及範圍並沒有那麼廣,所以這裏要聲明一下需求範圍。

積分獲取方式

支付、賬户服務、金融理財、掃一掃等。

同步方案:這個就涉及到AOP的思想,換言之“廣義AOP”。這個不是單個系統能實現的,需要多方系統共同確認,而本系統需要提供可靠的積分累計接口。如:用户支付完成後應該累計積分的,通過什麼方式與積分系統交互增加積分呢?這樣的接口如何設計呢?除了用户唯一標識、積分值、交易時間、交易類型還有什麼必要字段呢?需不需要重試?如何做冪等?分佈式事務如何考慮?等等,還有很多要素要考慮。

異步方案:有時我們對於積分累積的時效性並不高,就可以考慮異步方案。異步無非就是消息隊列類的異步任務,或是有數據團隊來做數據的分析處理。異步任務方式不管是消息隊列或是事件驅動都大概可行,當然這中間也有很多地方要注意。數據分析處理有點像是定時任務,描述可能不太準確,就是通過分析用户實際數據來具體分析處理,如:每天2點,數據團隊有多個數據模型針對不同的數據表(賬户存款、理財等等)對用户前一天所有交易進行分析,計算積分然後累計前一天產生的積分。

關於積分獲取方式,本次就討論到這了。其實上面簡單分析已經包含了很多系統設計的必要考慮條件了,而且很多都可以類比的,比如積分累計不就是類似購物產生訂單,或是記錄操作日誌嗎。有很多相似之處的,可以類比思考一下。

積分領取規則

從前面積分領取規則可以確定,積分領取涉及消息通知和過期。

消息通知肯定是成體系的,可參考其他消息類系統設計。過期可以參考下面的積分過期。

積分有效期

這個是本篇文章中我想要突出的重點。積分產生、積分兑換、積分過期還是需要好好思考一下的,如若不然,甚至不單單是產生系統bug,甚至會有業務bug,這是難以接受的。

既然上面需求説明了積分有效期是12個自然月,那麼就可以考慮設計一張按月存儲的表來存儲積分。

如5.1-5.31的產生的積分存儲為一條可用積分記錄,過期時間為5.31 23:59:59,總積分值為最近12個月積分之和。

用户ID 累計積分 可用積分值 過期時間
1 300 300 5.31 23:59:59
1 500 500 6.30 23:59:59
1 800 700 7.31 23:59:59
1 500 400 8.31 23:59:59
1 300 200 9.30 23:59:59
1 300 100 10.31 23:59:59
1 500 500 11.30 23:59:59
1 600 600 12.31 23:59:59

可能有人在接到積分過期需求時就考慮到定時任務掃表的方式,雖然可能也是沒問題的,但細節其實挺多的,這裏就不做過多討論了。

積分權益兑換

用户日常使用的積分,將優先使用即將過期的積分。針對於上面的月度積分表,在積分兑獎時從最早的未過期的月開始計算扣減積分。

設計方案

數據表

簡單設計如下,月度積分關聯多條積分明細記錄,這樣可以方便查詢月度積分獲取和消耗明細。

月度積分

  • 月度積分id
  • 用户id
  • 年月(參考2024-01之類的)
  • 累計積分
  • 可用積分
  • 過期時間

積分明細

  • 月度積分id
  • 明細id
  • 用户id
  • 積分值
  • 類型(如:消耗,獲取等)
  • 操作
  • 時間

兑獎明細

  • 兑獎明細id
  • 用户id
  • 獎品消耗積分
  • 獎品名稱
  • 時間

流程

積分獲取

積分由用户操作生成,同時存儲於月度積分表和積分明細表。

積分兑獎

其他

除了上面這些,還有

  • 總積分查詢,最近12個月的月度積分-可用積分之和
  • 積分明細查詢,倒序查詢月度積分和月度積分明細
  • 積分兑獎明細,等,簡單的就不多提了

參考代碼

積分兑獎

import java.time.LocalDate;
import java.util.*;

class PointRecord {
    private int points;
    private LocalDate expirationDate;

    // 構造方法、getters和setters省略

    public boolean canConsume(int requiredPoints) {
        return this.points >= requiredPoints;
    }

    public void consume(int requiredPoints) {
        if (canConsume(requiredPoints)) {
            this.points -= requiredPoints;
        } else {
            throw new IllegalArgumentException("Insufficient points to consume.");
        }
    }
}

public class PointService {
    public void redeemReward(User user, int rewardPointCost) {
        List<PointRecord> sortedRecords = getSortedUnexpiredPointRecords(user);

        for (PointRecord record : sortedRecords) {
            if (record.canConsume(rewardPointCost)) {
                record.consume(rewardPointCost);
                rewardPointCost = 0; // 已經滿足消耗條件,跳出循環
                break;
            } else {
                rewardPointCost -= record.getPoints();
                record.setPoints(0); // 消耗完該記錄所有積分
            }
        }

        // 更新數據庫中的積分明細表
        updateDatabase(sortedRecords);

        // 如果rewardPointCost仍然大於0,説明積分不足,需要在此處處理異常情況
        if (rewardPointCost > 0) {
            throw new InsufficientPointsException("Not enough valid points to redeem the reward.");
        }
    }

    // 省略了獲取用户未過期且已排序的積分記錄列表的方法(getSortedUnexpiredPointRecords)以及更新數據庫的方法(updateDatabase)
}

在這個示例中,PointRecord類代表單個積分記錄,包含積分值和過期日期。PointService中的redeemReward方法首先獲取用户的所有未過期且按過期時間排序的積分記錄,然後遍歷這些記錄,優先扣除最早到期的積分。當所需兑換積分數量減為0時停止扣除。如果最後仍有剩餘的兑換積分需求,則拋出積分不足的異常。

實際應用中,你需要根據數據庫查詢結果填充sortedRecords列表,並在扣除積分後更新數據庫以反映新的積分狀態。

小結

其實還有很多內容沒有細究,這部分就留給認真看的你們了。哈哈哈😂

積分補償、退貨等場景,分佈式事務如何考慮,留給你們了。

最後的最後,其實在系統設計之前,需求分析是重中之重,一定要講需求看透,尤其是多考慮一些場景。

下面有一張關於積分過期和兑獎的場景草圖,是我在思考時畫的,不想多解釋了,自己看吧😁

最後四個字:跳出時間。

寫在最後

拙作艱辛,字句心血,望諸君垂青,多予支持,不勝感激。


個人博客:無奈何楊(wnhyang)

個人語雀:wnhyang

共享語雀:在線知識共享

Github:wnhyang - Overview

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.