打碼指南:由貓眼線下掃碼1分購談起 | 掘金直播第11期總結
大家好, 今天給大家分享的是打碼指南, 由貓眼線下掃碼1分購談起.
小程式在釋出之後是沒有入口的, 之後確定是由線下掃二維碼進入, 今天分享的是我們自己嘗試在下線投放二維碼, 進行促銷活動, 中間經歷了一些波折. 這裡給大家介紹一下中間經歷的事情.
先做下自我介紹, 在2015年加入美團之前, 一個是去哪兒, 一個是CSDN, 再之前在西安, 主要是外包專案, 企業資訊管理系統. 之前在做Java, 當時沒有前端工程師的崗位, 但日常工作做前端比較多, 後面大家會看到有時有前端, 有時沒有前端的介紹, 這是因為我個人準全棧的經歷導致. 如果有志向做PM的話, 也建議關注下, 因為一個好的PM, 你應該知道這個東西是怎麼工作起來, 都有哪些人蔘與, 每個人負責什麼東西, 這個也是很有幫助的.
回到主題, 我們今天大概介紹這4個點
- 小程式碼和二維碼的約束
- 產出物料後修改需求
- 優惠券和使用者觸達通知
- 線上監控發現的問題
第1點和業務無關, 純技術的描述. 因為後面在介紹業務相關的場景的時候, 為了說的更流暢, 所以需要先介紹下小程式碼和二維碼的約束.
小程式碼和二維碼的約束
類似菊花那種, 官方名字叫小程式碼, 我們在日常溝通當中不會在意這個細節, 反正都能掃, 都叫二維碼.
方案A: getWXACode
path: 'pages/movie/index?arg=foo' 複製程式碼
限制:
- path引數限制128位元組長度
- 呼叫總數量限制: 10w個, 如果超過微信會拒絕後續的介面請求, 直接出錯, 提示超量
方案B: getWXACodeUnlimt
仍舊是菊花碼, 引數包括
path: 'pages/movie/index' scene: 'arg=foo' 複製程式碼
限制:
- path 不能加query引數
- scene 長度限制32個字元
在業務場景中不是很通用, 只能固定落地頁, 但是我們掃碼的目的還是需要有一些線下的特點能夠傳過來, 如果使用scene引數傳遞額外引數的話, 這個限制比上一個更苛刻, 但是它不限數量.
這個是在多數大規模投放二維碼的方案, 小規模的, 比如我們的今天要講的這個案例, 我們投放了大概2000多個影院, 其實這2個方案都可以.
方案C: createWXAQRCode
小程式官方叫小程式二維碼, 看起來和普通二維碼差不多, 由於二維碼本身有一定容錯能力, 所以LOGO放著是沒問題, 引數
path: 'pages/movie/index?arg=foo' 複製程式碼
限制:
- path 128位元組長度
- 呼叫總數量限制: 10w個, 和方案A公用配額
這個二維碼可以用普通掃碼程式掃描, 掃碼之後可以發現地址是mp.weixin.qq.com/a/
xxxxxxxxxxx
, 這是一個有意思的地方, 我們明明給傳的是上面的引數, 但是生成的是下面這個地址, 感覺是做了轉換.
前面介紹幾種形式, 限制和支援的引數, 儲存的資訊, 本質上這些資訊和URL差不多. 我們用二維碼連線線上線下, 二維碼本身儲存的資訊是路徑加引數.
傳統web開發我們需要關注URL上的輸入資訊, 比如query引數, 路徑, 特別是單頁應用的路由框架特別關注URL上的資訊.
可以理解URL也是一種輸入, 類似觸控. 所以二維碼也需要前端的同學關注, 因為我們要去處理二維碼背後的引數, 和我們的期望是否能匹配.
接下來看下實際案例, 和遇到的問題.
領取優惠券後, 期望能點選後退
我們線上下投放的業務, 通過易拉寶的形式, 掃上面的二維碼, 進入活動落地頁, 登入支付1分錢, 領取兩張優惠券, 分別用於支付電影和小吃如爆米花時抵扣. 投放位置是電影院, 我們的主要合作方.
需求第1階段
5塊的優惠券不是憑空出來的, 是得有人承擔的, 一般是平臺和商家互相分攤的. 平臺期望活動越多越好, 但是影院是有限度, 因為影院的規模, 活動成本有要求. 因此我們必須要識別出來是那家電影院, 涉及到財務結算, 不能錯.
我們的方案:
- 活動頁每家電影院帶上影院引數, 每家影院生成不一樣的二維碼
- 我們還需要打印出來
問題來了, 我們有2000家影院, 每家比如需要2份物料, 那麼我們需要列印4000份, 有2000種不一樣的二維碼.
物料一般是總部生產, 因為多數公司比較在意自己的品牌, 不會允許地下城市自己隨便生產涉及品牌形象的物料. 總部製作好之後還需要郵寄到各個城市, 把它放到具體的影院中.
正確的列印和郵寄, 人工不出錯才見鬼了. 快遞還可以直接看單子, 二維碼人不能直接識別, 列印錯了也難以發現.
所以直接按照這個方案走是很容易出錯的. 1%的出錯比例影響也比較大, 出錯的影院會直接找上門, 那就會是很大的麻煩.
為了避免出錯, 調整之後的方案, 我們印刷一個模板, 不包含二維碼, 因為物料只有二維碼部分是變的, 別的都不變, 這樣就可以批量的印刷, 批量的郵寄的問題. 如果郵寄出錯了, 我們可以把電子版素材發過去, 在當地印刷出來也來得及, 也允許電影院自行印刷更合適的介質.
二維碼通過影院後臺推送, 影院自行貼上, 這也是大家看一些大型活動二維碼和背後的物料是分離的原因.
看起來沒啥問題, 實際落地效果基本符合預期. 但接著就進入到一些更具體的業務場景
需求第2階段
進入活動落地頁, 完成簡單任務或直接領取優惠券, 領取優惠券之後期望支援後退, 如果我們什麼額外的都不做, 左上角什麼都沒有, 沒有後退, 只能點右上角關閉, 再進來又是活動頁.
使用者就會疑問, 我領了優惠券到哪裡去花呢?
所以需求肯定會要求支援回退, 跳轉到能消費優惠券的地方. 之前在掘金小程式開發者大會當中有講師也提到過, 左上角的後退按鈕對使用者體驗和資料的提升很重要的, 前端就需要考慮怎麼實現這個需求.
最笨的辦法: 先到首頁, 首頁再做一次重定向到活動頁, 一般我們期望後退到首頁.
另一個方案是自定義導航, 相當於頁面是全屏的, 只是在右上角浮出2個小程式自身的按鈕, 關閉和選單按鈕. 但這個方案有一些限制, 我們最後沒有用這個方案.
使用第一個方案的話, 二維碼變了, 雖然沒超過128位元組, 但已經印刷的二維碼就不能用了, 這就麻煩了, 還得重新生成二維碼, 重新印刷, 並貼上上去.
如果真的是這樣走一步看一步, 走到這肯定出問題, 肯定會吐槽.
更多需求
實際不僅僅如此
- 期望能後退到別的頁面
- 一家影院在不同入口放置的二維碼效果如何?
- 期望知道影院入口的效果
- 引數越來越多, 長度超限怎麼辦?
類似的需求越多, 引數就會越多. 如果是方案B的二維碼, 引數限制只有32位, 如果是方案A, 總長度128能稍好一些, 但反覆生成二維碼很有可能超過10w個數量限制.
最終會發現產出物料後改需求是一個常態, 我們如何才能支援這個常態.
短網址服務
這時就回到了我們提到的那個有意思的方案C, 我們提交的引數是一個地址, 但它生成的二維碼實際儲存的是另外一個地址, 很像短網址服務有沒有. 我們是不是也可以做一個這樣的服務, 客戶端的方案如下
- 入口:
path: 'pages/jump?id=3a5fc8'
, id引數表示一個短網址的id, 這個用於生成二維碼 -
pages/jump
頁面- 請求後端
wx.request({ url: 'xxxx', data: '3a5fc8' })
- 期望獲取到
{ path: 'pages/movie/index?go=pages/onecent/index?cinema=15280&utm_source=foo' }
- 期望獲取到
-
wx.redirectTo({ url: path })
- 請求後端
這個 path
就沒什麼長度限制, 這樣就可以完美的控制後退導航行為, 以及增加類似 utm_source
的埋點引數, 用於跟蹤放在影院的不同入口掃碼意願的差異.
做這些需要前端 後端 PM整體協商合作.
接下來看看服務端我們期望它有什麼功能
- 建立短網址 API : 因為我們會批量建立
- 批量查詢和修改 API : 因為是批量建立的, 我們又有產出物料後改需求的常態
- 短網址的額外資訊
- 類別 : 同一活動屬於同一類別
- 附加資訊 : Map結構, 比如包含 影院ID, 後退的頁面地址, 埋點資訊等, 為了通用性
最終我們生成的二維碼包含的 path 資訊是: pages/jump?id=3a5fc8
, 我們只需要到短網址服務後臺修改就可以控制它的行為.
更多
這個方案需求是解決了, 但由於多了箇中間頁, 可能介面是白的, 最多加個loading態, 改善下體驗, 但時間上可能會有點問題, 比原來要慢些.
一般的解決辦法, 首次進入快取, 第2次進入直接使用快取資料, 但仍舊發一個請求出去, 響應了再更新快取, 這樣無論快取過期還是別的狀況, 請求都不會阻塞.
更進一步, 我們可以生成一個http的地址, 其它的程式也能掃碼成功, 不限於微信.
http://m.maoyan.com/jump?id=3a5fc8 複製程式碼
比如我們期望使用一個二維碼, 任何終端掃碼都能進入活動. 我們期望微信掃碼開啟小程式, 這樣體驗更好, 其它程式掃碼開啟h5頁面.
微信掃普通二維碼能開啟小程式, 這個能力來自小程式管理後臺, 叫"掃普通連結二維碼開啟小程式", 只需要配置一個URL模式, 模式限制數量10個.
有些公司可能小程式公眾號參與者許可權互相有隔離, 所以實施這個會有一些溝通工作.
小結
- 需求是多變的: 基礎需求, 後退, 埋點等訴求, 這是一種常態
- 物料產出後難以修改: 隨著需求變更而重新生產物料是不現實的
- 短網址服務: 最終的方案
我們現在已經能讓使用者掃碼, 進入活動頁, 領取優惠券, 後退回到首頁, 完成購票流程.
但不是所有使用者都會走購票流程, 比如使用者現在想去吃飯, 就會關閉小程式走了, 這種情況我們 就只能等使用者來購票.
顯然我們不能等使用者來購票, 這樣在體驗上還是差點, 使用者領取了優惠券, 但是沒有消費是我們不願意看到的.
優惠券和使用者觸達通知
我們期望使用者領了優惠券之後能通知使用者, 方案有兩種
- 微信支付優惠券
- 自建優惠券
微信支付優惠券
微信支付 預充值代金券
- 入口: 訊息列表 "微信支付" 服務號
- 時機: 領取時, 即將到期時
- 滿減 商品限制 預算限制
- 防刷 對賬 消耗記錄
需要先充值, 會佔用一些現金, 有做PM的同學需要注意這點
前端需要注意 商品限制 , 有這種限制的時候, 需要前端把商品標記傳給微信支付API
自建優惠券
有些公司可能不太願意提前墊付資金, 這樣對現金流有要求, 那麼就可能需要自建優惠券.
如果要做到類似微信支付優惠券的體驗, 我們需要做
- 入口: 訊息列表 "服務通知"
- 時機: 自由
- 滿減 限制商品 預算限制
- 防刷 對賬 消耗記錄
限制
- 要使用服務通知, 所有訊息都需要憑證, 憑證通過表單 form 標籤 和支付能收集到, 也就是使用者必須有點選行為, 7天有效期
- 前端需要刻意在小程式上儘量收集這些憑證, 因為需求是多變的, 可能一開始說發2次就行, 後續又說需要發4次
- 客訴, 使用者覺得騷擾, 會給微信投訴, 微信會直接刪除訊息模板, 訊息就發不出去, 投訴再多就可能觸犯了小程式的規定, 有封號可能
- 一定要告知給PM, 特別是業務流程需要這個通知, 一定不要做違規的試探行為
- 防刷 對賬對於後端來說工作量還是很大的
小結
自建優惠劵需要做的工作很多, 初創公司建議直接使用微信支付優惠券, 特別是合規 防刷 對賬
自建優惠券, 前端需要注意多收集憑證, 通過 form + button
線上監控發現的問題
至此, 我們的活動上線, 使用者領了優惠券後, 既能現場買票, 也可以過一段時間收到通知, 得知還有優惠券可以去買票.
上線後還需要觀察服務本身有什麼意外, 由於我們對於多數的非同步呼叫都做了監控, 所以...
無法完成登入
wx.getUserInfo() 的返回中包含 signature: 簽名引數, 正常流程是返回了使用者暱稱 頭像資訊後需要進行數字簽名並比對是否一致, 不一致就表示有問題, 一般是認為獲取使用者資訊失敗.
但實際中發現Android 5.x系統下的微信客戶端, 如果使用者暱稱中如果包含 emoji 字元, 那麼 signature 肯定不一致. 此時使用者暱稱中的 emoji 字元實際ASCII值為 0xFEFE 這樣的字元, 一般看起來是亂碼.
解決方案: 除了等android 5.x基本消失, 就是如何符合上述條件, 可以忽略這個數字簽名比對, 暱稱只能獲取到個大概, 基本夠看.
任何微信介面呼叫可能失敗
我們呼叫了很多微信的介面, 比如 wx.login 相關, 生成二維碼. 有時會超時, 小程式端上的表現是卡頓, 隔了很久提示網路錯誤, 偶發, 很難復現, 大概0.5%.
對於百萬以上日活使用者的app來說, 這個問題還是挺嚴重的, 有些使用者如果點選後發現沒響應, 就停在這了, 使用者會認為你的小程式有問題, 直接關閉退出了.
調研的結論是網路問題, 微信這邊給的方案是嘗試用api2.weixin.qq.com, 也就是我們需要實現一個容災 重試策略.
我們最終實現了一個延遲重試的策略, 上線後呼叫微信介面的可用性從 99.5% 上升到 99.99%+.
cat監控系統
我們用過的一些異常收集系統, 或者在系統出問題的時候, 收集系統也掛掉了, 或者不夠實時, 或者沒有合適的分類, 只見樹不見林, 無法知道整個問題的情況, 不容易抓住重點.
我們發現上述問題主要依賴一個叫cat的系統
ping%2Fcat" rel="nofollow,noindex">github.com/dianping/ca…
基於java, 吞吐量 負載能力超強, 分類聚合滿足需求
總結
- 我們介紹了小程式二維碼的約束
- 需求變化導致我們需要支援產出物料後改需求, 我們通過短網址服務來支援這個業務
- 我們期望促銷活動能產生使用者消費, 需要通知使用者使用優惠券, 介紹了兩種方案的利弊, 成熟的公司可能兩種方案都要支援
- 上線的非同步呼叫 遠端呼叫監控, 發現的2個問題及其解決方案.
回顧下標題, 打碼指南: 由貓眼線下掃碼1分購談起, 靠譜的線下掃碼活動需要技術團隊提供那些支撐.
我們討論了需要開發什麼樣的系統, 關注什麼流程, 那些約束條件需要周知給各方. 因為前端所有的工作都是在一個宿主環境下, 都有很多的限制, 我們需要在各種限制的條件下完成各種需求.
Q&A
- 為什麼沒有使用自定義導航欄的方案
自定義導航欄, navigationStyle: custom 1.9.5 開始支援, 但需要 整個小程式 所有頁面都自定義導航欄才行, 這對於我們的場景不太適用, 只能作為長遠打算
- 能講下延遲重試策略麼?
根據我們的監控統計, 請求微信的介面95%的都會在650ms內響應, 大於這個時間最終請求超時的概率就很大了, 所以最終策略是
一旦請求在650ms內未完成, 立即發出後備請求, 直到任意一個獲得響應, 並且是正確的響應內容
這個策略我們開發成了一個superagent外掛, 後續會考慮開源出來
- 這麼看做線下掃碼活動成本 門檻還是有點高, 有什麼別的方法能減少這方面成本?
我們最初還考慮過另一種方案, 可以通過定位, 讓使用者選擇附近商家, 會在體驗 運營自由度上有折扣, 但可以規避各種二維碼物料的問題.
不過最後還是沒有用這個方案, 如果可接受體驗上的折扣, 還是可以用這種方案的.
其次就是把上文提到的二維碼相關功能做成服務開放出來, 我也有關注提供這方面支援的網際網路產品, 目前看未有發現.

,歡迎大家觀看學習和收藏~