• 实战丨如何制作一个完整的外卖小程序(已开源)


    最近微信小店开放了,赶着微信全面开放之前,把自己的小程序开源出来给大家使用~

    小程序效果

    开发心得

    如何在项目中集成云开发

    一开始项目并非基于云开发而开发的,目前考虑用云开发,因此,需要在项目中开启云开发的相关选项。

    首先,在小程序文件夹中建立 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 获取源码,自行使用~

  • 相关阅读:
    html5跨域通讯之postMessage的用法
    zTree插件之多选下拉菜单代码
    css3创建一个上下线性渐变色背景的div
    zTree插件之单选下拉菜单代码
    PhoneGap中navigator.notification.confirm的用法详解
    CCS3属性之text-overflow:ellipsis;的用法和注意之处
    HTML5的自定义属性data-* 的用法解析
    HSSFWorkbook转MultipartFile InputStream转MultipartFile
    @Transactional
    synchronized volatile
  • 原文地址:https://www.cnblogs.com/CloudBase/p/13391297.html
Copyright © 2020-2023  润新知