1. 程式人生 > 實用技巧 >實戰丨如何製作一個完整的外賣小程式(已開源)

實戰丨如何製作一個完整的外賣小程式(已開源)

最近微信小店開放了,趕著微信全面開放之前,把自己的小程式開源出來給大家使用~

小程式效果

開發心得

如何在專案中整合雲開發

一開始專案並非基於雲開發而開發的,目前考慮用雲開發,因此,需要在專案中開啟雲開發的相關選項。

首先,在小程式資料夾中建立 cloud 資料夾,並在package檔案中配置,建立使用者登入的雲函式並上傳到微信小程式雲中。相關的操作可以參考官方文件

我在專案目錄中添加了 cloudminiprogram 兩個目錄,並在 project.config.json 資料夾進行配置

{
   "miniprogramRoot": "./miniprogram"
   "cloudfunctionRoot": "./cloud/"
}

開通雲開發

配置完成後,可以點選控制檯中的「雲開發」來開通雲開發。

在雲開發的介面中配置,並開通雲開發。

開通資料庫集合

雲開發不會自動建立資料庫集合,因此,你需要手動建立集合。分別建立 店鋪表Seller、分類表Category、商品表Food、訂單表Order、地址表Address、使用者表_User

資料操作

有了資料庫的表後,就可以在程式碼中對資料進行操作了。

下方是我進行目錄操作的程式碼。

const db = wx.cloud.database()
const { showModal } = require('../../utils/utils')

Page({
  onLoad: function(options) {
    // 管理員認證
    getApp().auth()
    if (options.objectId) {
      // 快取資料
      this.setData({
        isEdit: true,
        objectId: options.objectId
      })
      // 請求待編輯的分類物件
      db.collection('Category')
        .doc(options.objectId)
        .get()
        .then(res => { 
        // 獲取分類資訊
          this.setData({
            category: res.data
          })
        })
    }
  },
  add: function(e) {
    var form = e.detail.value
    if (form.title == '') {
      wx.showModal({
        title: '請填寫分類名稱',
        showCancel: false
      })
      return
    }
    form.priority = Number.parseInt(form.priority)

    // 新增或者修改分類
    // 修改模式
    if (this.data.isEdit) {
      const category = this.data.category
      db.collection('Category')
        .doc(category._id)
        .update({
          data: form
        })
        .then(res => {
          console.log(res)
          showModal()
        })
    } else {
      db.collection('Category')
        .add({
          data: form
        })
        .then(res => {
          console.log(res)
          showModal()
        })
    }
  },
  showModal() {
    // 操作成功提示並返回上一頁
    wx.showModal({
      title: this.data.isEdit ? '修改成功' : '新增成功',
      showCancel: false,
      success: () => {
        wx.navigateBack()
      }
    })
  },
  delete: function() {
    // 確認刪除對話方塊
    wx.showModal({
      title: '確認刪除',
      success: res => {
        if (res.confirm) {
          const category = this.data.category
          db.collection('Category')
            .doc(category._id)
            .remove()
            .then(res => {
              console.log(res)
              wx.showToast({
                title: '刪除成功'
              })
              wx.navigateBack()
            })
        }
      }
    })
  }
})

聯表查詢

在使用資料庫時,難免要進行聯表查詢,雲開發支援在雲函式側進行聯表查詢,你可以參考我的程式碼,來實現聯表查詢的功能。

const cloud = require('wx-server-sdk')

cloud.init()

const db = cloud.database()

// 雲函式入口函式
exports.main = async (event, context) => {
  const result = await db.collection('Food')
    .aggregate()
    .lookup({
      from: 'Category',
      localField: 'category',
      foreignField: '_id',
      as: 'categories'
    })
    .end()
    // .orderBy('priority', 'asc')
    // .get()
    console.log(result)
    return result.list
}

檔案上傳

在小程式的操作中,難免會遇到需要進行圖片上傳的場景。在進行圖片上傳時,雲開發提供了方便的雲端儲存供我們查詢資料。

在獲取到檔案的本地路徑後,呼叫 wx.cloud.uploadFile 即可上傳檔案。

chooseImage() {
    wx.chooseImage({
      count: 1, // 預設9
      sizeType: ['compressed'], // 可以指定是原圖還是壓縮圖,預設二者都有
      sourceType: ['album', 'camera'], // 可以指定來源是相簿還是相機,預設二者都有
      success: res => {
        const tempFilePaths = res.tempFilePaths
        const file = tempFilePaths[0]
        const name = utils.random_filename(file) //上傳的圖片的別名,建議可以用日期命名
        console.log(name)
        wx.cloud.uploadFile({
          cloudPath: name,
          filePath: file, // 檔案路徑
        }).then(res => {
          console.log(res)
          const fileId = res.fileID
        // 將檔案id儲存到資料庫表中
          db.collection('Seller').doc(this.data.seller._id)
          .update({
            data: {
              logo_url: fileId
            }
          }).then(() => {
            wx.showToast({
              title: '上傳成功'
            })
            // 渲染本地頭像
            this.setData({
              new_logo: fileId
            })
          }, err => {
            console.log(err)
            wx.showToast({
              title: '上傳失敗'
            })
          })
        })
      }
    })
  }

微信支付邏輯的實現

作為一個商城,難免會有微信支付相關邏輯的實現。在這種情況下,可以藉助雲開發提供的微信支付雲呼叫功能實現快速的 API 呼叫和介面的實現。

繫結商戶

在使用雲開發提供的微信支付時,需要先執行微信支付的繫結,在雲開發控制檯新增相應的商戶號

新增後微信會發來通知

根據提示,開通賬號即可。

如果不繫結,將報“受理關係不存在”的錯誤

函式程式碼呼叫

配置完成後,只需要在雲函式中呼叫微信支付的介面,就可以實現相關呼叫的能力

const cloud = require('wx-server-sdk')

cloud.init({
  env: cloud.DYNAMIC_CURRENT_ENV
})

// 雲函式入口函式
exports.main = async (event, context) => {
  console.log('請求中')
  console.log(cloud.getWXContext().ENV)
  let { orderId, amount, body } = event
  const wxContext = cloud.getWXContext()
  const res = await cloud.cloudPay.unifiedOrder({
    body: body,
    outTradeNo: orderId,
    spbillCreateIp: '127.0.0.1',
    subMchId: '1447716902',
    totalFee: amount,
    envId: 'dinner-cloud',
    functionName: 'pay_cb'
  })
  return res.payment
}

這裡 functionName: 'pay_cb'指的就是支付成功後,微信支付那側給我的回撥資訊,後面我們就用它來更新我們的訂單狀態

小程式端程式碼呼叫

呼叫雲函式後,會獲得微信支付所需要的各種引數,

這個時候,就可以在小程式端呼叫微信支付介面,進行支付,相關程式碼可以參考

const { result: payData } = res
  wx.requestPayment({
    timeStamp: payData.timeStamp,
    nonceStr: payData.nonceStr,
    package: payData.package,
    signType: 'MD5',
    paySign: payData.paySign,
    success: res => {
      console.log('支付成功', res)
      wx.showModal({
        title: '支付成功',
        showCancel: false,
        success: () => {
          // 跳轉訂單詳情頁
          wx.navigateTo({
            url: '/order/detail/detail?objectId=' + order._id
          })
        }
      })
    },
...

微信支付回撥處理

微信統一下單裡一個pay_cb回撥函式,它是一個雲函式,後續微信支付的支付資訊將會發送在這個函式中,相應的,我們需要編寫處理的方法

// 雲函式入口檔案
const cloud = require('wx-server-sdk')

cloud.init({
  // API 呼叫都保持和雲函式當前所在環境一致
  env: cloud.DYNAMIC_CURRENT_ENV
})
const db = cloud.database()

// 雲函式入口函式
exports.main = async (event, context) => {
  console.log('支付回撥')
  console.log(event)
  console.log(cloud.getWXContext().ENV)
  const orderId = event.outTradeNo
  const resultCode = event.resultCode
  if (resultCode === 'SUCCESS') {
    const res = await db
      .collection('Order')
      .doc(orderId)
      .update({
        data: {
          status: 1
        }
      })
    console.log(res)
    return { errcode: 0 }
  }
}

總結

雲開發體驗下來,優點自不必多說,微信登入與支付原生支援,呼叫與除錯都很方便,特別是不用啟本地服務開發,真的好用;

這個小程式的原始碼我已經開源了,你可以訪問 Gitee 獲取原始碼,自行使用~