小程序模板網

實戰(zhàn):“贊賞”小程序前后端完整設計與代碼講解

發(fā)布時間:2017-12-01 15:24 所屬欄目:小程序開發(fā)教程

微信小程序推出以后,我在公司內部開過幾場小程序開發(fā)培訓課。出于培訓課程需要,以公眾號“贊賞 ...

 
 
 

微信小程序推出以后,我在公司內部開過幾場小程序開發(fā)培訓課。出于培訓課程需要,以公眾號“贊賞”功能作為需求,制作出一個“贊賞”小程序DEMO。

本案例涵蓋前后端完整設計與代碼講解,其中包括2個小程序前端頁面,3個后端JSON接口,涉及到的相關知識要點包括了登錄、后端信息獲?。ˋES-128-CBC解密算法)、微信支付、后端數(shù)據(jù)存儲等,是個完整的麻雀案例。

案例借助開源NAMI框架( https://github.com/wodenwang/nami ),十分鐘即可完成前后端本地部署。

案例效果一覽:

小程序登錄

微信公眾平臺(包括公眾號、小程序)相比APP的一個明顯優(yōu)勢,是開發(fā)者可以直接利用微信的用戶鑒權體系,免去注冊、密碼登錄的步驟。微信小程序對于登錄的設計,更是用之于無形,在整個用戶使用過程中都是無感知的,一進小程序其實就已經登錄了。

也許有讀者會說,小程序登錄的時候不是會彈出一個用戶信息的詢問框嗎?錯了,這個詢問框是調用wx.getUserInfo獲取“用戶資料”時候彈出的,調用wx.login的“登錄”操作是不會彈出任何詢問框的。

關于微信小程序登錄,官方文檔的流程實現(xiàn)起來挺不容易的(如下圖),需要服務端維護一個保存OpenID等用戶資料的緩存池,同時小程序客戶端還需要維護一個3rd session key,并且在之后每次做服務端請求的時候都要帶入這個3rd session key。

所幸NAMI框架已經把這塊封裝好,下面我們用一點篇幅來看看案例是如何做Login。

(1) app.js

import nami from '/nami/index';

App({
  data: {
    userInfo: null,
    rankLoaded: false //排行榜已加載
  },

  onLaunch: function () {
    var app = this;
    //登錄
    nami.login(() => {
      nami.getUserInfo((userInfo) => {
        console.log("已獲取數(shù)據(jù)", userInfo);
        app.data.userInfo = userInfo;
      }, () => {
        console.log("用戶拒絕提供信息");
      });
    });
  }
})

案例在小程序入口的時候實現(xiàn)nami封裝的登錄,登錄成功之后可以看到localstorage中保存了一個叫做NAMI_TOKEN的字符,這個就是小程序登錄之后要求前端保存的3rd session key了。

(2) rank.js

/**
     *下拉刷新
     */
    onPullDownRefresh: function () {
        wx.stopPullDownRefresh();
        var that = this;
        //這里使用了nami封裝的request而不是wx.request
        nami.request({
            loading: true,
            url: '/request/scholes_pay/rank.groovy',
            success: function (res) {
                that.setData({
                    dataList: res.data.list
                });
                app.data.rankLoaded = true;//加載完成
            }
        });
    },

截取一個服務端請求的代碼片段做分析,發(fā)現(xiàn)NAMI框架將request也做了封裝,其主要目的是在每次服務端請求的時候將localstorage中的NAMI_TOKEN帶入,如圖。

(3)服務端代碼:rank.groovy

/**
 * 排行榜
 * @author woden
 */

//重點是這一句獲取已登錄的用戶信息
//NAMI框架中通過nami_token在服務端緩存池找到對應的用戶資料,并返回給邏輯代碼
//這里的session指的是NAMI框架中封裝的會話上下文
def user = session.appUser();

//根據(jù)被贊賞金額排名的用戶列表
def list = db.query("""
select b.*,a.TOTAL_FEE from
(
    select sum(TOTAL_FEE) TOTAL_FEE,OPEN_ID from PAY_DETAIL group by OPEN_ID
) a 
left join PAY_USER b on a.OPEN_ID = b.OPEN_ID
order by a.TOTAL_FEE desc,b.UPDATE_TIME asc 
limit 10
""".toString());

def result = [];
def i=1;
for(def o:list){
    def vo = [:];
    vo.avatar = o.AVATAR_URL;
    vo.nickName = o.NICK_NAME;
    vo.fee = fmt.formatPrice(o.TOTAL_FEE/100);
    if(user.openId == o.OPEN_ID){
        vo.my = true;
    }
    vo.rank = i++;
    result += vo;
}

return [list:result];

從這個案例看出,NAMI框架遵循規(guī)范推薦的技術原則,將緩存池、3rd key等業(yè)務無關的技術細節(jié)封裝在框架中,讓開發(fā)人員可以更專注于業(yè)務邏輯本身。

小程序支付

小程序推出之初,許多開發(fā)人員對于小程序支付的實現(xiàn)也是焦頭爛額,官方給出的時序圖如下,讀者可以自己感受一下。

微信小程序的支付對于前端的接口倒是簡單,只需事先一個wx.requestPayment接口,至于API里面指定的參數(shù),填空就是了。先看看案例中前端支付是怎么寫的。

(1)index.js

/**
   * 綁定選中贊賞金額按鈕
   */
  selectItem: function (event) {
    //獲取待支付金額,單位:元
    var total = event.currentTarget.dataset.item;
    var that = this;
    that.setData({ selected: total });

    //向服務端發(fā)起支付請求,獲取wx.requestPayment需要的信息
    nami.request({
      loading: true,
      url: '/request/scholes_pay/pay.groovy',
      data: {
        total: total * 100 //元轉為分
      },
      success: function (res) {
        console.log("獲取支付密匙", res);

        //發(fā)起支付,根據(jù)服務端的返回填空
        wx.requestPayment({
          timeStamp: '' + res.data.signature.timestamp,
          nonceStr: res.data.signature.nonce,
          package: res.data.signature.pack,
          signType: 'MD5',
          paySign: res.data.signature.signature,
          success: function (res) {
            app.data.rankLoaded = false;//通知排行榜重新加載
            wx.showToast({
              title: '支付成功,感謝',
              icon: 'success'
            });
          },
          fail: function (res) {
            wx.showToast({
              title: '已取消支付',
              icon: 'success'
            });
          },
          complete: function () {
            that.setData({ selected: 0 });//取消選中
          }
        });

      },
      fail: function (res) {
        //do anything
      }
    });
  }

上面的代碼看出,調用wx.requestPayment之前需先請求服務端下單,并返回對應的支付密匙信息。好,接下來我們看看服務端下單的邏輯怎么寫。

(2)服務端代碼:pay.groovy

/**
 * 下單支付
 * 
 * @author woden
 *
 */

//獲取當前用戶
def user = session.appUser();
log.debug("user:{}",user);
if(!user?.nickName){
    nami.error("用戶拒絕提供資料,無法支付.");
}

//更新用戶信息
if(db.find("select OPEN_ID from PAY_USER where OPEN_ID=?",user.openId)){//找得到則更新
    db.exec("update PAY_USER set NICK_NAME=?,AVATAR_URL=?,UPDATE_TIME=? where OPEN_ID=?"
            ,user.nickName
            ,user.avatarUrl
            ,now
            ,user.openId
            );
}else{//否則新增
    db.exec("insert into PAY_USER (OPEN_ID,NICK_NAME,AVATAR_URL,UPDATE_TIME) values (?,?,?,?)"
            ,user.openId
            ,user.nickName
            ,user.avatarUrl
            ,now
            );
}

//支付下單
//調用NAMI框架的app.pay.order接口(封裝了微信支付下單),直接獲取訂單order對象
def total = request.getInteger("total");
def order =app.pay.order([
    openId : user.openId,
    total : total,
    body : '多謝贊賞',
    notify : nami.invoke('host.groovy')+'/request/scholes_pay/pay_callback.groovy' //回調
]);

//向客戶端生成支付加密串
//調用NAMI框架的app.pay.signatur接口(根據(jù)prepayId換取支付密匙)
return [tradeNumber:order.tradeNumber,signature:app.pay.signature(order.prepayId)];

這里NAMI有兩個接口,分別是:

  • app.pay.order :統(tǒng)一下單;
  • app.pay.signatur :簽名算法。

NAMI框架已將接口調用、基于支付安全考慮的簽名加密算法都封裝好,讓開發(fā)人員關注業(yè)務邏輯本身而非這些技術細節(jié),這在實際項目開發(fā)的時候可以大大提升效率。

踩坑

即使開發(fā)這么小的案例,數(shù)數(shù)也踩了不少坑,除了像兼容性問題、工具BUG、各種組件BUG這種已經讓開發(fā)者們“習以為常”的坑以外,我重點列幾個被官方升級“升”出來的坑。

  • 獲取用戶資料的確認框被“拒絕”后不再彈出,導致獲取不到用戶資料。 調用wx.getUserInfo彈出詢問框,假如點了“拒絕”之后,再次調用wx.getUserInfo不再彈出,任你結束進程、清理緩存都沒有,硬是要等大概十多分鐘后,才會再次彈出詢問框。這時候可別再點錯了,否則又得等十多分鐘。 
    這是小程序某個版本升級“升”出來的。在此之前我看過有些產品喜歡把wx.getUserInfo設計成用戶主動點擊按鈕去獲取的事件,例如設計一顆“登錄”按鈕,用戶一點擊就調用wx.getUserInfo,用戶點擊“允許”就相當于登錄了;這個“十多分鐘不彈出”的特性升級之后,以前這類主動登錄的模式就得改改了。
  • 內置的Promise被廢除。 一開始看到小程序支持ES6,支持Promise的時候非常高興,想著可以寫更優(yōu)雅的異步代碼塊了。誰知道在某個版本升級之后,Promise就不被支持了,實在不知何故。雖然說有一些例如es6-promise的第三方框架可以代替,但不是終歸總是不爽。
  • 地理位置API,獲取不了當前坐標對應的地名。
  • 我一怒之下使用百度地圖API實現(xiàn)了,還是終歸不爽。

最后說個血淚小教訓,調試微信支付的時候千萬千萬不要用銀行卡或信用卡去測試,頻繁的支付1分錢1毛錢1塊錢,會導致卡被銀行封掉。

另外用內置的DB console可以查看案例的運營數(shù)據(jù),觀摩一下。讀者可以看出誰贊賞了最多,最多又是多少錢嗎?

下載源碼:大家可以從 Github獲取“贊賞”案例源碼 。



易優(yōu)小程序(企業(yè)版)+靈活api+前后代碼開源 碼云倉庫:starfork
本文地址:http://22321a.com/wxmini/doc/course/18012.html 復制鏈接 如需定制請聯(lián)系易優(yōu)客服咨詢:800182392 點擊咨詢
QQ在線咨詢