1.背景
18年快年底的時(shí)候,有一天突然想要不要做一個(gè)搶紅包的小程序春節(jié)期間玩玩,但是又不能直接跟微信一樣直接搶吧,后面想著就引入答題這種模式,答對(duì)一次搶一次紅包,答對(duì)可一直搶到最后,答錯(cuò)則結(jié)束搶紅包,大概就是這樣一個(gè)玩法,看著挺簡(jiǎn)單的一個(gè)功能,其實(shí)全流程下來(lái)要考慮的點(diǎn)也是不少,下面就簡(jiǎn)單做一個(gè)思路的介紹:
2. 資質(zhì)相關(guān)的一些問(wèn)題
1.申請(qǐng)小程序:
小程序個(gè)人、企業(yè)都可以申請(qǐng),但是因?yàn)樾枰t包涉及到支付功能,必須企業(yè)資質(zhì),所以找代理注冊(cè)了一家公司,注冊(cè)公司全流程也還是挺多事的,這里不細(xì)講,反正有了公司后,又進(jìn)行了微信公眾號(hào)認(rèn)證,然后用企業(yè)資質(zhì)申請(qǐng)小程序,微信支付等。
2.小程序服務(wù)類(lèi)目:
紅包類(lèi)小程序因?yàn)樯婕暗接脩?hù)資金,按照規(guī)范服務(wù)類(lèi)目應(yīng)該使用社交紅包,但是該類(lèi)目下同樣要求《增值電信業(yè)務(wù)經(jīng)營(yíng)許可證》,該證辦理也比較麻煩,如果正式商業(yè)化建議還是辦理,我們暫時(shí)使用的其它類(lèi)目。

3.核心功能
1.包紅包
包紅包的時(shí)候設(shè)置題目、金額、數(shù)量,其中題目可自定義或者隨機(jī),自定義是用戶(hù)自己設(shè)置題干,選項(xiàng),答案等,隨機(jī)題使用的我們的題庫(kù),生成紅包后可分享小程序。
- 搶紅包
用戶(hù)點(diǎn)開(kāi)小程序,會(huì)隨機(jī)獲取一個(gè)題目,自定義題則從用戶(hù)自定義題庫(kù)里選,隨機(jī)題則從系統(tǒng)題庫(kù)中選,用戶(hù)答對(duì)后則獲得一個(gè)紅包,繼續(xù)答下一題,答錯(cuò)則結(jié)束搶紅包。 -
提現(xiàn)
搶到紅包后可馬上進(jìn)行提現(xiàn),提現(xiàn)功能使用的微信支付“企業(yè)付款到零錢(qián)功能”,該功能開(kāi)通有一個(gè)坑就是T+1結(jié)算周期入駐需滿(mǎn)90天,且最近30天連續(xù)不間斷保持交易,對(duì)于新開(kāi)的商戶(hù)肯定不滿(mǎn)足的,所以我們的結(jié)算周期用的T+7的,當(dāng)然結(jié)算周期其實(shí)是看微信支付商戶(hù)開(kāi)通的時(shí)候選擇的行業(yè)來(lái)的,不是自己決定的。
企業(yè)付款到零錢(qián)
4.風(fēng)險(xiǎn)點(diǎn)考慮
做跟錢(qián)打交道的功能,就一定要考慮風(fēng)險(xiǎn),比如是否會(huì)被攻擊,羊毛黨是否能褥羊毛,上線(xiàn)第一天就被攻擊了一波,當(dāng)時(shí)有個(gè)漏洞差點(diǎn)就被褥了。
- 搶紅包金額和數(shù)量不能搶到負(fù)數(shù)
假設(shè)群里面一百人搶最后一個(gè)紅包,那只能讓一個(gè)人搶到,或者別人惡意攻擊時(shí),大并發(fā)流量搶紅包。
解決方式:數(shù)據(jù)庫(kù)在減金額或者數(shù)量的時(shí)候where 后面加條件,如果寫(xiě)的代碼里面先從數(shù)據(jù)庫(kù)查出來(lái),發(fā)現(xiàn)金額或者數(shù)量滿(mǎn)足,就直接去減了,并發(fā)數(shù)高的時(shí)候,可能一百個(gè)請(qǐng)求去查的時(shí)候都是滿(mǎn)足的,但是最后數(shù)據(jù)庫(kù)去執(zhí)行的時(shí)候只一個(gè)滿(mǎn)足,沒(méi)控制好數(shù)據(jù)庫(kù)金額和數(shù)量就會(huì)減到負(fù)數(shù)。 - 提現(xiàn)的時(shí)候不能提現(xiàn)到負(fù)數(shù)
同樣的別人假設(shè)惡意攻擊,同時(shí)一百并發(fā)提現(xiàn),不能讓金額提現(xiàn)到負(fù)數(shù),防止惡意提現(xiàn)。
解決方案:同樣是在數(shù)據(jù)更新的時(shí)候加where條件,不能只在代碼里面校驗(yàn)。 - 生成紅包金額算法
算法是參考的網(wǎng)上的,實(shí)時(shí)計(jì)算紅包金額,沒(méi)有提前去生成各個(gè)紅包金額,實(shí)時(shí)計(jì)算規(guī)則每次生成紅包金額為[0.01,剩余紅包金額平均值*2),右邊是開(kāi)區(qū)間。
/**
* 獲取隨機(jī)金額,注意剩余金額不能小于0.01*remainNum
* @param remainMoney 剩余金額
* @param remainNum 剩余數(shù)量
* @return
*/
public static BigDecimal getRandomMoney(BigDecimal remainMoney, Integer remainNum) {
// remainSize 剩余的紅包數(shù)量
// remainMoney 剩余的錢(qián)
if (remainNum == 1) {
//如果只剩一個(gè),則返回所有金額
return remainMoney;
}
Random r = new Random();
double min = 0.01; //
double max = remainMoney.doubleValue() / remainNum * 2;
double money = r.nextDouble() * max;
money = money <= min ? 0.01: money;
money = Math.floor(money * 100) / 100;
return new BigDecimal(money);
}
5.關(guān)于性能
對(duì)性能要求高的就是搶紅包這塊,如果真的是大規(guī)模用戶(hù)用,搶紅包這塊的設(shè)計(jì)就很重要,我們有用到redis,但redis只是做了比如題目的緩存,搶紅包這塊目前還是寫(xiě)db,如果要提升性能的化,搶紅包過(guò)程可以全部走redis,異步更新到數(shù)據(jù)庫(kù),有考慮這塊的設(shè)計(jì),但時(shí)間問(wèn)題當(dāng)時(shí)沒(méi)有去實(shí)現(xiàn)。
最后放個(gè)小程序碼,有興趣的可以體驗(yàn)一下。

