如何做一個小程序口令紅包功能

2021-02-21 SegmentFault

在做小程序後端支持的過程中遇到不少有意思的功能,有些比較考你的思維散發及解決問題的實際能力,這裡摘錄一下記錄下來,是為拋磚引玉、如能幫到別人,自然是最好不過了。

先放幾張設計圖看下大概功能:

大概便是如此。

通過圖片可以看到,涉及到的稍微複雜一點的功能點有:語音文字識別、紅包分配算法,周邊紅包算法等等。 其餘的都是些簡單的CRUD操作。我CODING+TESTING用了差不多一周,以下說下各個功能點的大概實現思路及方法。

語音識別

應用場景:A用戶設置了一個中文的口令紅包,接收到該紅包的B用戶需要用語音說出該口令,完全匹配的話則獲取該紅包的某個比例金額。

錄音自然是調用小程序提供的原生接口,不過這裡比較坑的是微信的錄音格式是 .silk。網上搜索的方法是先將.silk格式轉成wav或者MP3格式,然後再調用各大雲服務平臺的接口實現語音識別功能。

這裡使用了 https://github.com/kn007/silk-v3-decoder 提供的庫用來轉成wav格式,然後使用百度的語音識別開放接口 https://ai.baidu.com/tech/speech/asr 來識別語音結果。

業務實現步驟如下:

1.前端實現錄音功能2.upload接口上傳.silk語音文件,入庫3.觸發語音識別task,返回成功給前端(異步)4.前端輪詢識別結果。

因為從上傳到識別到返回結果是一個耗時操作,所以識別過程最好是異步操作。(第三步)

upload語音接口部分代碼:

// ... 業務代碼略

$voice = $this->getCreatedVoiceByBody(); // 上傳併入庫

$this->identifyVoice($voice); // 觸發語音識別task

// ...

public function identifyVoice($voice)

{

   WorkerUtil::sendTaskByRouteAndParams('task/detectvoice', ['voiceid' => $voice->id, 'type' =>'redpack']);

}

如上可見,將一條包含了語音文件地址的記錄id及類型發送到了後端task服務。

後端task服務處理如下:

class DetectVoice extends Action

{

   public function run($voiceid, $type = 'redpack')

   {

       if ($type == 'redpack') {

           $voice = Voices::findOne($voiceid);

           $url = $voice->voice;

           $saveName = '/runtime/redpack-'.$voiceid.'.silk';

           $convertName = '/runtime/redpack-'.$voiceid.'.wav';

       }

       $this->saveToLocalByRemoteVoiceUrlAndLocalFileName($url, $saveName);

       $cfg = [

           'appKey' => 'xxx',

           'appSecret' => 'xxx',

           'appId' => 'xxx',

       ];

       $util = new BaiduVoiceUtil($cfg);

       $code = exec("bash /www/silk-v3-decoder/converter.sh {$saveName} wav");

       if ($code == 0) {

           $result = $util->asr($convertName);

           if ($result['err_no'] == 0) {

               $voicesResult = json_encode($result['result'], JSON_UNESCAPED_UNICODE);

               $voice->result = $voicesResult;

               $voice->save();

               @unlink($saveName);

               @unlink($convertName);

           }

       }

   }

   ...

}

task服務的處理邏輯也很清晰:接收需要識別的voiceid,查找記錄,把語音文件下到本地某個tmp目錄,調用shell轉換格式,將轉換後的格式調用baidu的語音接口進行識別,再將結果入庫。

voice表結構如下:

如此,便完成了語音識別功能。

紅包分配

應用場景:創建紅包時

打開紅包一般有兩種分配方法,一種是使用創建時便分配好每一份的份額。一種是打開時再動態分配,這裡採取的是第一種。

具體討論可在知乎:https://www.zhihu.com/question/22625187 找到。

說實話,看完這個答案還是學到了一些東西的,如微信紅包的架構實現,分配寫法等等。

因為我們的應用沒有微信的量級,自然不需要考慮太多(負載,並發等),產品的要求也只是說金額這方面要實現類微信紅包的分配方法即可。因此,考慮到擴展及性能以及時間,分配寫法我直接採用了 陳鵬 的答案裡的寫法,不過是變成了PHP的版本。並且搭配了redis 作為紅包份額的存儲及可能的並發問題處理方案。

先上代碼(redpack/create):

$redpack = $this->getCreatedRedPackByBody();

// ... 業務邏輯代碼略

// 設置隨機紅包份額

$this->setRedPackOpenOdds($redpack);

protected function setRedPackOpenOdds($rp)

{

   $remainNum = $rp->num;

   $remainMoney = $rp->fee;

   $key = 'redpack:'.$rp->id;

   $redis = yii::$app->redis;

   while (!empty($remainNum)) {

       $money = $this->getRandomMoney($remainNum, $remainMoney);

       $redis->executeCommand('RPUSH', [$key, $money]);

   }

   $redis->executeCommand('expire', [$key, 259200]);

}

protected function getRandomMoney(&$remainNum, &$remainMoney)

{

   if ($remainNum == 1) {

       $remainNum--;

       return $remainMoney;

   }

   $randomNum = StringUtil::getRandom(6, 1);

   $seed = $randomNum / 1000000;

   $min = 1;

   $max = $remainMoney / $remainNum * 2;

   $money = $seed * $max;

   $money = $money <= $min ? $min : ceil($money);

   $remainNum--;

   $remainMoney -= $money;

   return $money;

}

這部分代碼邏輯也相對簡單,主要就是:

將當前金額和份數傳入函數( getRandomMoney),在計算出當次的隨機金額後,將該金額寫入redis的一個list (key=redpack:id),然後將總金額和總份數減去,一直減完為止。

有幾點值得注意的地方:

1.原答案裡的隨機數生成法使用了 java.math.BigDecimal. 可php沒有對應的函數,自帶的隨機數也不好用。這裡用的自己寫的隨機數生成方法 (獲取6位的隨機數字,然後除以它們的位數,就得到類似於 0.608948的隨機數)2.每個紅包的份額設置了一天的過期時間,這是為了實現紅包過期的功能。

redis裡的結果(單位為分):

10元分配15個

100元分配7個:

50元分配25個:

可以看到基本實現了隨機分配,也兼顧了手氣最佳的要求。

使用也簡單,打開紅包獲取份額的時候,使用這個list左邊一個個出棧就行了。

紅包地圖

應用場景:查看周圍發布的紅包

這個實現的關鍵之處就是周邊的坐標算法。首先,前提條件是創建紅包時要獲取到經緯度坐標,這個交由前端實現,我們只記錄即可。

然後在調用這個接口時,把用戶當前的經緯度傳過來。根據這個經緯度計算出周邊範圍,然後查找表中在這個周邊範圍的記錄即可。

代碼如下:

/**

*

* @param double $lng 經度

* @param double $lat 緯度

* @param integer $radius 範圍

* @return array

*/

public function run($lng, $lat, $radius = 500)

{

   $coordinates = $this->getAroundByCoordinates($lng, $lat, $radius);

   $field = 'id,lat,lng';

   $data = (new Query())

           ->select($field)

           ->from('{{app_redpack}}')

           ->where(sprintf("`lat` BETWEEN %f AND %f AND `lng` BETWEEN %f AND %f AND `ishandle` = 1 AND `isexpire` = 0", $coordinates[0], $coordinates[2], $coordinates[1], $coordinates[3]))

           ->all();

   return ResponseUtil::getOutputArrayByCodeAndData(Api::SUCCESS, $data);

}

/**

* 地球的圓周是24901英裡。

* 24,901/360度 = 69.17 英裡 / 度

* @param double $longitude 經度

* @param double $latitude 緯度

* @param integer $raidus 範圍。單位米。

* @return array

*/

public function getAroundByCoordinates($longitude, $latitude, $raidus)

{

   (double) $degree = (24901 * 1609) / 360.0;

   (double) $dpmLat = 1 / $degree;

   (double) $radiusLat = $dpmLat * $raidus;

   (double) $minLat = $latitude - $radiusLat;

   (double) $maxLat = $latitude + $radiusLat;

   (double) $mpdLng = $degree * cos($latitude * (pi() / 180));

   (double) $dpmLng = 1 / $mpdLng;

   (double) $radiusLng = $dpmLng * $raidus;

   (double) $minLng = $longitude - $radiusLng;

   (double) $maxLng = $longitude + $radiusLng;

   return [$minLat, $minLng, $maxLat, $maxLng];

}

關鍵就是getAroundByCoordinates 這個算法,它根據輸入的經緯度及範圍大小,計算出左上,左下,右上,右下四個角的坐標,在地圖上標出來的話就是 一個長方形的範圍。

有興趣的可以根據 http://lbs.qq.com/tool/getpoint/ 這個工具,隨意點取一個坐標,根據以上的方法算出四個角,看看是不是剛好是$raidus指定的範圍。

需要說明的是這個方法不是我寫的,但是我實在不記得出處在哪了。我只是記得把java的實現方法改成了php。對原作者說聲抱歉。

相關文章推薦

PHP 紅包算法

PHP 與微信支付那些事(公眾號支付、掃碼支付、企業付款、發紅包)

摩拜單車微信小程序開發技術總結

歡迎關注 SegmentFault 微信公眾號 :)

相關焦點

  • 防騙|一個「口令」5000元紅包沒了!小心口令紅包騙局!
    要王先生先設置一個口令紅包,然後自發自領,並提供相關的流水號給他,李某自稱能通過公司的同事查詢訂單號,然後驗證王先生的帳戶安全性。李某還告訴王先生,紅包金額不能太小,最好是5000元左右。王先生沒有多想,就按照李某的要求,先自發自領了兩個紅包。而當王先生在發完第三個口令紅包時,店裡來了客人,王先生還沒來得及自己領取紅包,就急忙去招待客人了。
  • 你說包微信口令紅包沒領到?微信口令紅包沒領到解決方案
    你說包微信口令紅包沒領到?微信口令紅包沒領到解決方案 你說包微信口令紅包是微信口令中一個比較好玩的小程序,既然是小程序,那麼就一定存在一些問題,今天小編給玩家們帶來你說包微信口令紅包沒領到的解決方案。你說包微信口令紅包沒領到?別急!
  • 微博怎麼發口令紅包 微博口令紅包在哪裡
    現在口令紅包鋪天蓋地,不過口令紅包的確比普通紅包好玩,特別是對於表白什麼的挺有意思,現在微博也可以發口令紅包了,那麼微博如何發口令紅包呢?首先我們打開微博app,然後登錄,找到下方的加號,如圖所示,點擊加號在這裡可以發微博,發文字、照片視頻、頭條文章、籤到等等,如果要發紅包,我們點擊【更多】然後就可以看到其中有一項是紅包,我們點擊【紅包】當然我們還可以通過另外一種方式進入微博紅包,我們在首頁中,點擊【我】,然後在頁面中找到【微博支付】進入微博支付,我們就點擊【微博紅包
  • 微信口令紅包領取入口
    對於很多用戶來說微信就是生活中和工作中和其他人交流的工具,也是生活中比較經常用到的,所以在微信中發發紅包是很正常的,其中微信是可以發口令紅包的,但是很多用戶不知道,那麼下面就讓小編給大家介紹一下微信口令紅包怎樣發。仔細算一下年化利率約為14%。大部分剪紙是軸對稱的`。要安靜。人們不再騎自行車、摩託車了。6.南瓜南瓜具有豐富的營養。夏天的食材也比較多。
  • 雙十二感恩紅包口令怎麼使用?雙十二感恩紅包口令大全
    川北在線核心提示:原標題:雙十二感恩紅包口令怎麼使用?雙十二感恩紅包口令大全 雙十二感恩紅包口令怎麼使用?很多用戶對於這個口令還不是很清楚,小編為大家帶來,雙十二感恩紅包口令大全。 雙十二感恩紅包口令怎麼使用?
  • 一個「口令」,5000元紅包瞬間「飛」走
    口令紅包本來是給大家帶來快樂的一種發紅包的方式,但讓人意想不到的是,竟然有人會利用口令紅包來詐騙。近日,南京市江寧公安分局開發區派出所接到轄區內一家眼鏡店報警,店鋪負責人說自己被騙了5000元錢。要王先生先設置一個口令紅包,然後自發自領,並提供相關的流水號給他,李某自稱能通過公司的同事查詢訂單號,然後驗證王先生的帳戶安全性。李某還告訴王先生,紅包金額不能太小,最好是5000元左右。王先生沒有多想,就按照李某的要求,先自發自領了兩個紅包。而當王先生在發完第三個口令紅包時,店裡來了客人,王先生還沒來得及自己領取紅包,就急忙去招待客人了。
  • 微信包你說語音口令紅包惡搞句子大全 生僻字語音口令詞語
    不知道大家最近發現沒,有很多人在朋友圈裡曬語音口令,更多的是在微信群裡面發語音口令,說對了就能領紅包,這種語音口令紅包可能大家都遇到過,這是最近微信上新出的一個小程序,叫包你說,有些小夥伴們就遇到過不少的惡搞口令或者是很多生僻字,讓人哭笑不得!下面一起來看看吧!
  • 支付寶紅包口令,餘額寶消費紅包,萌萌你省錢
    就在去年,支付寶推出一款紅包活動,很多人都領到大額紅包,很多人都不敢相信自己能領到這麼大的紅包,然而近日支付寶又推出支付寶紅包和餘額寶消費紅包活動,其實很多人都不知道支付寶紅包怎麼領取,那就讓小編來告訴你。
  • 從新品抽獎小程序思考微信工具型小程序的發展
    抽獎小程序主要功能是為服務商提供營銷服務,上線至今,同類型產品眾多。本篇文章選取了五個具有代表性的抽獎小程序,分別為大家介紹其各自的功能板塊,再對此進行分析,通過對目前市場上的小程序的發展情況的詳細分析,思考未來工具型小程序的發展方向。
  • 揭秘最新的灰色暴利「小程序領紅包」,很多人已經被套路
    在網際網路上做項目,不做負面項目,封建迷信項目,不做有法律風險的項目。網際網路上入門了,你就會發現誘惑非常多。小編個人的建議是,創業,我們必須做正規項目,絕對不犯罪。絕對不為了錢鋌而走險。前幾天就有新聞爆出了「小程序領紅包」的暴利灰色項目,怎麼回事呢,先看下圖:這是一個對口令領紅包的小程序,一共發了15000個紅包,每個錢還挺多的。按照每個人領了10元紅包計算的話,這個紅包金額至少10萬+,很土豪有沒有。
  • 運營了一款免費的抽獎工具小程序,做活動的時候用還是蠻不錯的!
    ,這個小程序其實19年就已經做出來了, 只是遲遲沒有時間去運營。抽獎類的小程序是如何做增長的,看到市面上做的比較好的幾家,他們的區別大部分是收費上的區別,要麼是分為免費的基礎版本,要麼是付費的高級版本。免費的增長自然是更快的,雖然會損失一部分收入,不過這樣的方式能夠解決種子用戶的問題。
  • QQ語音口令紅包惡搞語句大全 難念的繞口令語音口令句子
    大家玩過qq新推出的語音口令紅包(玩法介紹)嗎?這個口令是可以設置的,任意的語音詞語都可以哦,想必有的親們就想惡搞自己的好友了,下面就由小編為您詳細介紹介紹哦。  qq語音口令紅包繞口令介紹:  榴槤流奶牛角包」 「紅鯉魚與綠鯉魚與驢」  1、一面小花鼓,鼓上畫老虎。
  • 360國慶活動搜索紅包節獎勵內容 輸紅包口令關鍵詞開啟紅包
    領取到的紅包怎麼提現?360搜索給大家送福利了哦,還可以搶購國慶節紅包獎勵,下面就由小編為您詳細介紹介紹哦。  360搜索紅包節活動介紹:  活動從10月1日到10月9日,整整九天每天發放十萬紅包,最大單包高達1000元。用戶只要在電腦上,使用360搜索,在搜索框內輸入特定的搜索關鍵詞(紅包口令),就會彈出活動彩蛋。
  • 大魚創意原創案例:看節目,聽口令,解鎖微信紅包新玩法!
    微信口令紅包隨著微信的普及,微信紅包已經成為人與人、品牌與用戶互動的重要方式,這種附帶紅包的品牌線下吸粉營銷,可以讓品牌營銷達到事半功倍的效果。>支持自定義三種玩法模式,普通模式、輸入手機號碼和輸入口令模式;支持自定義背景、背景色、抽獎頂部廣告、抽獎紅包圖等;支持設置秒顯廣告功能;支持直接連結和二維碼圖片調用活動的功能;獎品支持紅包和卡券功能
  • 2020淘寶雙12紅包口令領取入口,大額雙十二紅包怎麼領?
    2020淘寶雙12紅包口令領取入口,大額雙十二紅包怎麼領? 雙十二想買的便宜,挑選折扣力度大的商家和商品下單當然是非常必要的,不過領取雙十二的紅包福利和參與雙十二玩法同樣的重要,都是可以幫助大家省錢的哈,首先來給大家講一下今年淘寶雙十二紅包的領取方法。 淘寶雙12超級紅包領取入口 2020年天貓的雙十二紅包如何領取呢?保存下面紅包口令,每天3次,最高1212元。
  • 京東天貓雙11紅包口令入口,京東京享紅包天貓超級紅包領取方法大全
    一年一度的雙11又來了,在雙十一有很多玩法優惠活動,今天小編給大家分享下。 天貓紅包淘口令:4¥GHscc771ov0¥/(複製口令打開手淘app即可) 電腦端紅包地址:https://s.click.taobao.com/cYDbLvu複製到電腦端即可領取紅包 京東紅包入口 如果你是京東買東西就領取京東的紅包,京東紅包複製三次口令每天可以領取三次,隨領隨用超級方便,而且每天必中現金紅包,這是比較給力的一點,而且還有較大概率中大額紅包
  • 2020天貓雙11紅包口令時間表 蹲點搶淘寶紅包
    複製此段淘 口令¥JSF3c7OBIKa¥打開手機淘寶app,即可免費領取超級紅包!保存這段話,每天可以搶3次,最高1111元紅包。 可能此刻還有人問,什麼是超級紅包?簡單點說,超級紅包是由天貓官方出資的紅包,淘寶天貓用戶只要領取了紅包,就可以直接當現金使用了,最高1111元的紅包哦,而且今年官方還出來了6個玩法,接下去小編會一一給大家介紹,先劃重點:重點一:如何領取超級紅包???
  • 「剖析」小程序能做什麼,你的需求是否適合做小程序
    它既是一個社交產品,又是一個超級App,還是一個瀏覽器,更是一個作業系統。總之,每個人對於微信都有自己不同的定義。我們在設計小程序時,一定要想明白微信官方希望自己承載的東西是什麼以及希望第三方的產品的邊界是什麼。張小龍曾公開分享過,他希望微信成為一個網際網路超級工具 。微信曾經有過四次重要的版本迭代歷史,每一次迭代都是一個飛躍,都讓微信變成一個新物種。
  • 2020淘寶雙11超級紅包口令倒計時,雙十一紅包最高1111元
    2020淘寶雙11超級紅包口令倒計時,雙十一紅包最高1111元 2020年10月20日 17:40作者:黃頁編輯:黃頁 淘寶雙11超級紅包領取入口 2020年天貓的雙十一紅包如何領取呢?將會在10月21日0點開始發放,最高的金額為1111元!
  • 2021淘寶/天貓年貨節紅包口令入口,年貨節紅包什麼時候開始?
    淘寶年前基本沒有什麼活動了,短短一個月的時間,也只有年貨節這個比較大型的活動了。今天要跟大家講的是,2021年年貨節怎麼領超級紅包?什麼時候可以領?年貨節紅包(超級紅包新春特別版)領取入口2021年天淘寶年貨節紅包如何領取呢?保存下面紅包口令,每天可領。