灵犀外卖之使用微信小程序云开发

帅比萌擦擦* 提交于 2020-08-11 13:04:12

#摘要

在官方的微信小店全开放前开源一波

效果演示

首页

后台

v1-done.gif

集成云开发

旧项目是非基于云开发的,建立cloud文件夹,并在package文件中配置,建立用户登录的云函数并上传到微信小程序云中

建立云函数文件夹,并在package.config.json配置为云函数目录

文档详见:[https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/functions/getting-started.html ](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/functions/getting-started.html )

建立页面文件夹,miniprogram,将旧小程序项目的pages文件夹一并移入该文件夹中,并配置在package.config.json中,{..."miniprogramRoot": "miniprogram/"...}

开通云开发

image.png

image.png

创建数据表

分别创建 店铺表Seller、分类表Category、商品表Food、订单表Order、地址表Address、用户表_User image.png

怎么建立用户表

用户表是不是需要自己创建,不存在类似于Bmob、LeanCloud这些云存储那样默认存在_User表

数据表的特征

  1. 当数据是从小程序端创建数据的,天然就带有_openid字段
  2. 添加数据必须保证数据表已经存在,不存在就创建集合这跟之前用过的Bmob、LeanCloud一类的云存储不同,后者遇到引用不存在集合是会自动创建集合的

创建云函数

写完云函数本地调试完毕后,要将远程的也更新一下

上传增量更新

image.png

本地调试

image.png

如果没有安装依赖的,要切换到云函数目录,运行npm install安装它

image.png

表数据的权限问题

假如没权限,.get请求数据,得到的数据是空白的,而不是报错无权限

那么就是权限没有,默认是仅创建人可读可写

修改文档也是一样,打算修改店铺资料,但从返回信息看是修改成功,实则数据未改成功过,这是就自定义权限,read/write都设置为true了。

修改权限可以按如下方式修改

image.png

数据的增删改查

引入const db = wx.cloud.database()后,就是一系列关键字,get/doc/add/update/remove这些了

看下面这个分类表的操作

/*
 *
 * 关注订阅号【huangxiujie85】,第一时间收到教程推送
 *
 * @author 黄秀杰
 */

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()
            })
        }
      }
    })
  }
})

表关联

商品表关联分类表

lookup做联表查询时,报错

errCode: -502003 database permission denied | errMsg: Permission denied Error: errCode: -502003 database permission denied | errMsg: Permission denied

image.png

版本要求:wx-server-sdk 1.3.0 或以上 不支持在小程序端使用

好坑,提示是权限问题,发现是本来就不支持,联表查询下,还要在云上写

老老实实地写云函数吧

// 云函数入口文件
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
}

这样就能使用.aggregate().lookup作联表查询了

图片上传

图片上传重点是取出fileID,它可以直接赋值给<image />的src属性就是渲染到页面上了,微信一家就是这么好说话

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: '上传失败'
            })
          })
        })
      }
    })
  }

微信支付

优点,都不用开启后端服务,有点要调试发现后端都还没怎么就跑起来了,这种感觉之前没有的,很不习惯

调用简单

不用提供小程序的appid 支付的32位key,这些都在开发工具设置中绑定好了的,唯一提供的是商户的mchId就可以

因为本地没法得到微信支付的通知回调,在以前魔改路由,配花生壳域名,远程到服务器写代码,这都经历过,为的就是让回调被通知到微信支付的消息。

subMchId 子商户号,不知道从何而来,我这里就是传的自己申请到的商户号 传统写支付要用的mchid key为什么这里不需要,只要绑定就好

绑定微信支付商户

如下图先添加商户号添加

image.png

添加后微信会发来通知

image.png

按提示开通就好

image.png

如果不绑定,将报“理关系不存在”的错误

image.png

配置成功后,云函数中发起统一下单

// 云函数入口文件
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'指的就是支付成功后,微信支付那侧给我的回调信息,后面我们就用它来更新我们的订单状态

正常返回支付要用的参数了

image.png

上面的payment对象里的就是小程序端调用支付requestPayment时要用到的参数

配合以下小程序端的代码,就能唤起支付让用户付款了

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 }
  }
}

为了更好地调试微信支付给我的回调信息,可以进入云函数面板,日志标签页,那里给把我们云函数console.log()打印结果显示出来,如下图

image.png

使用第三方库tenpay实现

这个是通用解决方案,不用原生的云开发微信支付,自己写node.js后端就是这么干的

//云开发实现支付
const cloud = require('wx-server-sdk')
cloud.init()

//1,引入支付的三方依赖
const tenpay = require('tenpay')
//2,配置支付信息
const config = {
  appid: 'wx6f3d369c2xx1678f', //
  mchid: '1447716902', //
  partnerKey: '21f0ce9b272xxxba342f83994c438f39', //
  notify_url: 'https://mp.weixin.qq.com', //支付回调网址,这里可以先随意填一个网址
  spbill_create_ip: '127.0.0.1'
}

exports.main = async (event, context) => {
  const wxContext = cloud.getWXContext()
  let { orderId, amount, body } = event
  //3,初始化支付
  const api = tenpay.init(config)

  let result = await api.getPayParams({
    out_trade_no: orderId,
    body: body,
    total_fee: amount, //订单金额(分),
    openid: wxContext.OPENID //付款用户的openid
  })
  return result
}

缺点是无法回调通知支付结果notify_url: '',因为我们没有自己的后端服务器,也就没法提示这个url了,最多就是在前端轮询订单就支付状态进而改自己的订单的状态了。

总结

云开发体验下来,优点自不必多说,微信登录与支付原生支持,调用与调试都很方便,特别是不用启本地服务开发,真的好用;最大的不足就是小程序端不支持联表查询,必须写云函数被小程序调用,期待早日能像Bmob、LeanCloud一类的云存储那样得到支持。

源码下载

[https://gitee.com/laeser/dinner-cloud ](https://gitee.com/laeser/dinner-cloud ) 或者关注公众号huangxiujie85回复116

mp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!