# 微信小程序云迁移uniCloud

# 概念澄清

uniCloud,可以自选阿里云和腾讯云的serverless。类似于uni-app屏蔽了各家小程序的端侧差异,uniCloud也屏蔽了微信小程序云开发和支付宝小程序云开发的差异。

也就是说,uniCloud选择腾讯云时,和微信小程序云开发,连的是一套云服务,都是腾讯云官方提供的。

虽然硬件相同,包括API也很相似,但uniCloud和微信云开发仍然有一些软件层面的差异。

uniCloud去掉了微信云开发的一些功能,添加了更多功能。以及在生态配套上差别也比较大。

# 优劣对比

微信云开发 uniCloud
跨端 只有微信小程序(虽可用其他工具变相开发H5、QQ小程序,但端不够全也难以保持一致性) 全端。App、web、各家小程序快应用全支持
跨云 只支持腾讯云。为其编写的云函数不能运行在其他云平台 阿里云、腾讯云均支持,方便互相切换。对其他云也持开放态度
定价 价格相同。 价格相同。DCloud只是获取腾讯云的返点,而不是加价售卖
前端操作数据库 使用微信的账户权限而不是应用的账户权限,无法编程,不能有效控制数据权限安全。客户端js sdk体积大,影响性能 完善的clientDB (opens new window)模块,使用应用自己的用户权限体系,可灵活编程,安全可靠控制权限
数据库schema 不支持 完善的数据库schema (opens new window)设计,自带权限验证和数据合法性验证
数据库查询语法 MongoDB语法。学习门槛高、写法复杂,尤其联表查询很难用 除了MongoDB语法外,支持JQL语法,大幅降低学习门槛,减少数据库操作的代码量,快速完成复杂查询
开发工具 微信小程序工具,编码体验欠佳 通用编程工具HBuilderX,高效操作完善,插件体系开放
前端数据库watch 支持。权限按微信账户体系执行 有更强大的免费的websocket服务详情查看 (opens new window)
opendb 开放的数据库规范,众多价值,详情
账户服务 仅微信登录,但鉴权更简单 uni-id支持应用自己的账户体系,手机号或email,内置短信验证码和app端一键登录,支持微信、支付宝等三方登录,支持权限、角色、社交裂变等众多功能
admin系统 不自带 自带开源uniCloud admin (opens new window)系统,大小屏自适配,自带用户、角色、权限功能,还有更多插件 (opens new window)拿来即用
支付 仅微信支付,但鉴权更简单 uniPay (opens new window),跨端统一支付
cms 支持。但前端部分跨端不足 支持。前端跨端、管理端 (opens new window)开源
插件生态 腾讯云开发了部分插件 丰富的插件生态,包含腾讯云为uniCloud开发的插件,众多现成项目模块,详情 (opens new window)

上述差异,总结来看,uniCloud更开放、生态更丰富、开发效率更高。

开发效率之所以高的原因,包括clientDB、JQL、HBuilderX这些对效率起很大影响的重要功能和工具,也包括大量现成的轮子拿来就用。详见:2021了,让我们把开发效率提升10倍吧! (opens new window)

# 技术迁移指南

如果已经开发了微信小程序,想迁移到uniCloud,下面提供云函数和数据库部分的技术迁移指南。

# 云函数迁移指南

# 对接微信登录

uniCloud可以使用uni-id更简单的接入微信小程序登录。参考uni-id

不同于微信云开发中的直接获取openid,uni-id提供的登录接口会在数据库的uni-id-users表内添加用户记录。

如果要控制云存储的权限可以使用自定义登录,uniCloud腾讯云自定义登录 (opens new window)

# 对接微信支付

uniCloud提供了uniPay来实现支付功能,同时支持微信和支付宝unipay文档 (opens new window)

老的微信云开发+原生小程序的代码是这样:

// 云函数部分的代码
const cloud = require('wx-server-sdk')
cloud.init({
  env: cloud.DYNAMIC_CURRENT_ENV
})

exports.main = async (event, context) => {
  const res = await cloud.cloudPay.unifiedOrder({
    "body" : "商品描述",
    "outTradeNo" : "商户订单号",
    "spbillCreateIp" : "127.0.0.1",
    "totalFee" : 1,
	// 用于接收支付异步通知的云函数所在的服务空间ID和云函数名
    "envId": "test-f0b102",
    "functionName": "pay_cb"
  })
  return res
}

// 小程序部分的代码
wx.cloud.callFunction({
  name: '函数名',
  data: {
    // ...
  },
  success: res => {
    const payment = res.result.payment
    wx.requestPayment({
      ...payment,
      success (res) {
        console.log('pay success', res)
      },
      fail (res) {
        console.error('pay fail', err)
      }
    })
  },
  fail: console.error,
})

迁移到uniCloud + uni-app体系,代码改成这样:

// 云函数部分的代码
const unipayIns = unipay.initWeixin({
  appId: 'your appId',
  mchId: 'your mchId',
  key: 'you parterner key',
  // pfx: fs.readFileSync('/path/to/your/pfxfile'), // p12文件路径,使用微信退款时需要,需要注意的是阿里云目前不支持以相对路径读取文件,请使用绝对路径的形式
})


exports.main = async (event, context) => {
	const res = await unipayIns.getOrderInfo({
		openid: 'user openid',
		body: '商品描述',
		outTradeNo: '商户订单号',
		totalFee: 1, // 金额,单位分
		notifyUrl: 'https://xxx.xx' // 支付结果通知地址
	})
  return res
}

// 客户端部分的代码
uniCloud.callFunction({
	name: '云函数名',
	data: {
		// ...
	},
	success(res) {
		uni.requestPayment({
			provider: 'wxpay',
			...res.result.orderInfo
			success (res) {
			  console.log('pay success', res)
			},
			fail (res) {
			  console.error('pay fail', err)
			}
		})
	}
})

注意

  • uniPay和微信小程序的CloudPay接口很相似,需要注意的是uniPay接收的参数都是驼峰形式的,输出的参数也都是驼峰形式的。微信小程序的CloudPay有些接口是驼峰形式参数有些是蛇形参数

# 临时CDN

临时CDN主要用于解决需要传输大文件到云函数的场景,使用uniCloud时可以通过先上传到云存储再传递fileID给云函数的方式实现

微信云开发写法:

wx.cloud.callFunction({
  name: 'test',
  data: {
    filePathDemo: wx.cloud.CDN({
      type: 'filePath',
      filePath: 'xxxxxxxx',
    })
  },
})

uniCloud写法:

uniCloud.uploadFile({
	filePath: filePath,
	cloudPath: 'a.jpg'
}).then(res => {
	const fileID = res.fileID
	uniCloud.callFunction({
		name: 'test',
		data: {
			filePathDemo: fileID
		}
	})
})

# 微信开放接口

使用微信开放接口的场景可以替换为mp-cloud-openapi (opens new window)来实现。用法基本和微信云开发一致

微信云开发写法:

const cloud = require('wx-server-sdk')
cloud.init()
exports.main = async (event, context) => {
  try {
    const result = await cloud.openapi.wxacode.createQRCode({
        path: 'page/index/index',
        width: 430
      })
    return result
  } catch (err) {
    return err
  }
}

uniCloud写法:

// mp-cloud-openapi,地址:https://ext.dcloud.net.cn/plugin?id=1810
const openapi = require('mp-cloud-openapi')
const openapiWeixin = openapi.initWeixin({
  appId: 'appId',
  secret: 'secret'
})
exports.main = async (event, context) => {
  try {
    const result = await openapiWeixin.wxacode.createQRCode({
        path: 'page/index/index',
        width: 430
      })
    return result
  } catch (err) {
    return err
  }
}

# 数据库迁移指南

# 数据导出导入

微信小程序云开发的控制台可以导出json数据,这个格式与uniCloud相同,可以将导出文件直接在uniCloud的web控制台操作导入。

# 新增与更新数据的写法

微信小程序云开发add、update、set操作时参数比uniCloud多了一层data 从微信小程序云开发迁移时最需要注意的事项

微信云开发写法:

const res = await db.collection('todos').doc('todo-id').add({
  data: {
    description: "learn cloud database",
    done: false
  }
})

uniCloud写法:

const res = await db.collection('todos').doc('todo-id').add({
  description: "learn cloud database",
  done: false
})

# 客户端操作数据库

uniCloud内也支持客户端操作数据库(下面成为clientDB),但是与微信云开发稍有不同。主要有以下两点

  • 权限依赖于uni-id
  • 需要在表结构的permission里面配置权限,可以配置字段级的权限

另外clientDB支持以下扩展能力