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

小程序效果

云开发外卖小程序 - 图1
image
云开发外卖小程序 - 图2
image
云开发外卖小程序 - 图3
image

开发心得

如何在项目中集成云开发

一开始项目并非基于云开发而开发的,目前考虑用云开发,因此,需要在项目中开启云开发的相关选项。
首先,在小程序文件夹中建立 cloud 文件夹,并在package文件中配置,建立用户登录的云函数并上传到微信小程序云中。相关的操作可以参考官方文档
我在项目目录中添加了 cloudminiprogram 两个目录,并在 project.config.json 文件夹进行配置

  1. {
  2. "miniprogramRoot": "./miniprogram"
  3. "cloudfunctionRoot": "./cloud/"
  4. }

开通云开发

配置完成后,可以点击控制台中的「云开发」来开通云开发。
云开发外卖小程序 - 图4
image
在云开发的界面中配置,并开通云开发。
云开发外卖小程序 - 图5
image

开通数据库集合

云开发不会自动创建数据库集合,因此,你需要手动创建集合。分别创建 店铺表Seller、分类表Category、商品表Food、订单表Order、地址表Address、用户表_User
云开发外卖小程序 - 图6
image

数据操作

有了数据库的表后,就可以在代码中对数据进行操作了。
下方是我进行目录操作的代码。

  1. const db = wx.cloud.database()
  2. const { showModal } = require('../../utils/utils')
  3. Page({
  4. onLoad: function(options) {
  5. // 管理员认证
  6. getApp().auth()
  7. if (options.objectId) {
  8. // 缓存数据
  9. this.setData({
  10. isEdit: true,
  11. objectId: options.objectId
  12. })
  13. // 请求待编辑的分类对象
  14. db.collection('Category')
  15. .doc(options.objectId)
  16. .get()
  17. .then(res => {
  18. // 获取分类信息
  19. this.setData({
  20. category: res.data
  21. })
  22. })
  23. }
  24. },
  25. add: function(e) {
  26. var form = e.detail.value
  27. if (form.title == '') {
  28. wx.showModal({
  29. title: '请填写分类名称',
  30. showCancel: false
  31. })
  32. return
  33. }
  34. form.priority = Number.parseInt(form.priority)
  35. // 添加或者修改分类
  36. // 修改模式
  37. if (this.data.isEdit) {
  38. const category = this.data.category
  39. db.collection('Category')
  40. .doc(category._id)
  41. .update({
  42. data: form
  43. })
  44. .then(res => {
  45. console.log(res)
  46. showModal()
  47. })
  48. } else {
  49. db.collection('Category')
  50. .add({
  51. data: form
  52. })
  53. .then(res => {
  54. console.log(res)
  55. showModal()
  56. })
  57. }
  58. },
  59. showModal() {
  60. // 操作成功提示并返回上一页
  61. wx.showModal({
  62. title: this.data.isEdit ? '修改成功' : '添加成功',
  63. showCancel: false,
  64. success: () => {
  65. wx.navigateBack()
  66. }
  67. })
  68. },
  69. delete: function() {
  70. // 确认删除对话框
  71. wx.showModal({
  72. title: '确认删除',
  73. success: res => {
  74. if (res.confirm) {
  75. const category = this.data.category
  76. db.collection('Category')
  77. .doc(category._id)
  78. .remove()
  79. .then(res => {
  80. console.log(res)
  81. wx.showToast({
  82. title: '删除成功'
  83. })
  84. wx.navigateBack()
  85. })
  86. }
  87. }
  88. })
  89. }
  90. })

联表查询

在使用数据库时,难免要进行联表查询,云开发支持在云函数侧进行联表查询,你可以参考我的代码,来实现联表查询的功能。

  1. const cloud = require('wx-server-sdk')
  2. cloud.init()
  3. const db = cloud.database()
  4. // 云函数入口函数
  5. exports.main = async (event, context) => {
  6. const result = await db.collection('Food')
  7. .aggregate()
  8. .lookup({
  9. from: 'Category',
  10. localField: 'category',
  11. foreignField: '_id',
  12. as: 'categories'
  13. })
  14. .end()
  15. // .orderBy('priority', 'asc')
  16. // .get()
  17. console.log(result)
  18. return result.list
  19. }

文件上传

在小程序的操作中,难免会遇到需要进行图片上传的场景。在进行图片上传时,云开发提供了方便的云存储供我们查询数据。
在获取到文件的本地路径后,调用 wx.cloud.uploadFile 即可上传文件。

  1. chooseImage() {
  2. wx.chooseImage({
  3. count: 1, // 默认9
  4. sizeType: ['compressed'], // 可以指定是原图还是压缩图,默认二者都有
  5. sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
  6. success: res => {
  7. const tempFilePaths = res.tempFilePaths
  8. const file = tempFilePaths[0]
  9. const name = utils.random_filename(file) //上传的图片的别名,建议可以用日期命名
  10. console.log(name)
  11. wx.cloud.uploadFile({
  12. cloudPath: name,
  13. filePath: file, // 文件路径
  14. }).then(res => {
  15. console.log(res)
  16. const fileId = res.fileID
  17. // 将文件id保存到数据库表中
  18. db.collection('Seller').doc(this.data.seller._id)
  19. .update({
  20. data: {
  21. logo_url: fileId
  22. }
  23. }).then(() => {
  24. wx.showToast({
  25. title: '上传成功'
  26. })
  27. // 渲染本地头像
  28. this.setData({
  29. new_logo: fileId
  30. })
  31. }, err => {
  32. console.log(err)
  33. wx.showToast({
  34. title: '上传失败'
  35. })
  36. })
  37. })
  38. }
  39. })
  40. }

微信支付逻辑的实现

作为一个商城,难免会有微信支付相关逻辑的实现。在这种情况下,可以借助云开发提供的微信支付云调用功能实现快速的 API 调用和接口的实现。

绑定商户

在使用云开发提供的微信支付时,需要先执行微信支付的绑定,在云开发控制台添加相应的商户号
云开发外卖小程序 - 图7
image
添加后微信会发来通知
云开发外卖小程序 - 图8
image
根据提示,开通账号即可。
云开发外卖小程序 - 图9
image

如果不绑定,将报“受理关系不存在”的错误 云开发外卖小程序 - 图10 image

函数代码调用

配置完成后,只需要在云函数中调用微信支付的接口,就可以实现相关调用的能力

  1. const cloud = require('wx-server-sdk')
  2. cloud.init({
  3. env: cloud.DYNAMIC_CURRENT_ENV
  4. })
  5. // 云函数入口函数
  6. exports.main = async (event, context) => {
  7. console.log('请求中')
  8. console.log(cloud.getWXContext().ENV)
  9. let { orderId, amount, body } = event
  10. const wxContext = cloud.getWXContext()
  11. const res = await cloud.cloudPay.unifiedOrder({
  12. body: body,
  13. outTradeNo: orderId,
  14. spbillCreateIp: '127.0.0.1',
  15. subMchId: '1447716902',
  16. totalFee: amount,
  17. envId: 'dinner-cloud',
  18. functionName: 'pay_cb'
  19. })
  20. return res.payment
  21. }

这里 functionName: 'pay_cb'指的就是支付成功后,微信支付那侧给我的回调信息,后面我们就用它来更新我们的订单状态

小程序端代码调用

调用云函数后,会获得微信支付所需要的各种参数,
云开发外卖小程序 - 图11
image
这个时候,就可以在小程序端调用微信支付接口,进行支付,相关代码可以参考

  1. const { result: payData } = res
  2. wx.requestPayment({
  3. timeStamp: payData.timeStamp,
  4. nonceStr: payData.nonceStr,
  5. package: payData.package,
  6. signType: 'MD5',
  7. paySign: payData.paySign,
  8. success: res => {
  9. console.log('支付成功', res)
  10. wx.showModal({
  11. title: '支付成功',
  12. showCancel: false,
  13. success: () => {
  14. // 跳转订单详情页
  15. wx.navigateTo({
  16. url: '/order/detail/detail?objectId=' + order._id
  17. })
  18. }
  19. })
  20. },
  21. ...

微信支付回调处理

微信统一下单里一个pay_cb回调函数,它是一个云函数,后续微信支付的支付信息将会发送在这个函数中,相应的,我们需要编写处理的方法

  1. // 云函数入口文件
  2. const cloud = require('wx-server-sdk')
  3. cloud.init({
  4. // API 调用都保持和云函数当前所在环境一致
  5. env: cloud.DYNAMIC_CURRENT_ENV
  6. })
  7. const db = cloud.database()
  8. // 云函数入口函数
  9. exports.main = async (event, context) => {
  10. console.log('支付回调')
  11. console.log(event)
  12. console.log(cloud.getWXContext().ENV)
  13. const orderId = event.outTradeNo
  14. const resultCode = event.resultCode
  15. if (resultCode === 'SUCCESS') {
  16. const res = await db
  17. .collection('Order')
  18. .doc(orderId)
  19. .update({
  20. data: {
  21. status: 1
  22. }
  23. })
  24. console.log(res)
  25. return { errcode: 0 }
  26. }
  27. }

总结

云开发体验下来,优点自不必多说,微信登录与支付原生支持,调用与调试都很方便,特别是不用启本地服务开发,真的好用;
这个小程序的源码我已经开源了,你可以访问 Gitee 获取源码,自行使用~

云开发(Tencent CloudBase,TCB)是腾讯云提供的云原生一体化开发环境和工具平台,为开发者提供高可用、自动弹性扩缩的后端云服务,包含计算、存储、托管等serverless化能力,可用于云端一体化开发多种端应用(小程序,公众号,Web 应用,Flutter 客户端等),帮助开发者统一构建和管理后端服务和云资源,避免了应用开发过程中繁琐的服务器搭建及运维,开发者可以专注于业务逻辑的实现,开发门槛更低,效率更高。