小程序云的进阶开发技巧

本文涉及的产品
简介: 介绍小程序云函数以及云调用的进阶用法。

云数据库

云数据库(数据存储服务)是基于MongoDB托管在云端的数据库,数据以JSON格式存储。作为开发者,您可以在客户端内直接操作数据,也可以在云函数中读写数据。

数据库常用语法说明

数据存储服务是基于MongoDB托管在云端的数据库,使用MongoDB 3.4版本,常用的数据库操作语法如下。

聚合查询aggregate
计算记录条数count
删除一条数据记录deleteOne
删除一批数据记录deleteMany
获取去重后的记录distinct
查询记录find
查询单条记录findOne
查询并删除一条记录findOneAndDelete
查询并替换一条记录findOneAndReplace
查询并更新记录findOneAndUpdate
替换记录replaceOne
添加一批记录insertMany
添加一条记录insertOne
更新一批记录updateMany
更新一条记录updateOne

使用地理位置数据

小程序云支持以下几种地理位置数据类型:

  • Point,点
{ type: "LineString", coordinates: [ [ 40, 5 ], [ 41, 6 ] ] }
  • LineString,线
{ type: "LineString", coordinates: [ [ 40, 5 ], [ 41, 6 ] ] }
  • Polygon,多边形
{
  type: "Polygon",
  coordinates: [ [ [ 0 , 0 ] , [ 3 , 6 ] , [ 6 , 1 ] , [ 0 , 0  ] ] ]
}
  • MultiPoint, 点集合
{
  type: "MultiPoint",
  coordinates: [
     [ -73.9580, 40.8003 ],
     [ -73.9498, 40.7968 ],
     [ -73.9737, 40.7648 ],
     [ -73.9814, 40.7681 ]
  ]
}
  • MultiLineString,线段集合
{
  type: "MultiLineString",
  coordinates: [
     [ [ -73.96943, 40.78519 ], [ -73.96082, 40.78095 ] ],
     [ [ -73.96415, 40.79229 ], [ -73.95544, 40.78854 ] ],
     [ [ -73.97162, 40.78205 ], [ -73.96374, 40.77715 ] ],
     [ [ -73.97880, 40.77247 ], [ -73.97036, 40.76811 ] ]
  ]
}
  • MultiPolygon,多边形集合
{
  type: "MultiPolygon",
  coordinates: [
     [ [ [ -73.958, 40.8003 ], [ -73.9498, 40.7968 ], [ -73.9737, 40.7648 ], [ -73.9814, 40.7681 ], [ -73.958, 40.8003 ] ] ],
     [ [ [ -73.958, 40.8003 ], [ -73.9498, 40.7968 ], [ -73.9737, 40.7648 ], [ -73.958, 40.8003 ] ] ]
  ]
}

插入地理位置数据示例:

// 在小程序端  
my.serverless.db.collection('places').insertMany([
        {
          location: { type: "Point", coordinates: [-73.88, 40.78] },
          name: "La Guardia Airport",
          category: "Airport"
        },
        {
          location: { type: "LineString", coordinates: [[113, 23], [120, 50]] },
          name: "ss Airport",
          category: "Airport"
        }
  ]}
  // 在云函数中插入
 ctx.mpserverless.db.collection('places').insertMany([
        {
          location: { type: "Point", coordinates: [-73.88, 40.78] },
          name: "La Guardia Airport",
          category: "Airport"
        },
        {
          location: { type: "LineString", coordinates: [[113, 23], [120, 50]] },
          name: "ss Airport",
          category: "Airport"
        }
  ]}                                                

创建地理位置索引

可以通过控制台或者调用RunDBComand接口来创建地理位置类型的索引。以下为使用RunDBComand接口创建地理位置索引的Body参数示例。

{
    "command": "createIndex",
    "collection": "places",
    "field": {
        "location": "2dsphere"
    },
    "options": {
        "name": "location_2dsphere",
        "unique": false
    }
}

查询地理位置数据

您可以在小程序端或者云函数中来使用地理位置查询,两者的查询语法是相同的。支持以下几种查询方法:

  • nearSphere

     • 按从近到远的顺序,找出字段值在给定地点附近的记录。
    
// 使用nearSphere必须给查询的字段添加地理位置索引,否则会查询失败。
my.serverless.db.collection('places').find(
  {
    location: {
      $nearSphere: {
        $geometry: {
          type: "Point",
          coordinates: [-73.9667, 40.78]
        },
        $minDistance: 1000,
        $maxDistance: 5000
      }
    }
  }
);
  • geoWithin

     • 找出字段值在给定区域内的记录。给定区域可以是Polygon、MultiPolygon或者CenterSphere。
    
my.serverless.db.collection('places').find(
  {
    location: {
      $geoWithin: {
        $geometry: {
          type: "Polygon",
          coordinates: [
            [[0, 0], [30, 20], [20, 30], [0, 0]],
            [[10, 10], [16, 14], [14, 16], [10, 10]]
          ]
        }
      }
    }
  }
);
  • geoNear(聚合查询)

     • 适用于聚合阶段,将记录按照给定点从近到远输出。
    
my.serverless.db.collection('places').aggregate(
  [
    {
      $geoNear: {
        near: { type: "Point", coordinates: [113.323809, 23.097732] },
        distanceField: "distance",
        maxDistance: 2,
        query: { category: "Parks" },
        includeLocs: "location",
        spherical: true
      }
    }
  ]
);

设置数据库索引

使用数据库时,对成为查询条件的字段设置索引可以有效提高查询效率,更快的获取信息。缺省情况下会
对_id_字段默认创建一个非唯一索引。

1.在数据库页面,单击目标数据表,然后单击索引页签进入索引设置页面。
2.点击添加索引进入索引设置页面。
3.填写索引名称,设置索引属性、索引字段。

  • 索引属性:可以设置为唯一索引或非唯一索引。

将字段设置为唯一索引后,可以防止不同记录的被索引键上存储相同值。

  • 索引字段:支持单键索引和复合索引设置,字段按升序或降序排列。

单键索引是最常见的索引形式,针对一个指定字段建立索引。对于单字段索引,升序、降序的查询效果一样。
复合索引是是单键索引的升级版,针对多个字段联合创建索引,先按照第一个字段排列,第一个字段相同的记录按第二个字段排列,依次类推。

4.单击保存按钮,保存索引设置。

image.png

image.png

云函数

云函数(FaaS)是一段运行在云端的、轻量的、无关联的、并且可重用的代码。无需管理服务器,只需编写和上传代码,即可获得对应的数据结果。使用云函数可以使企业和开发者不需要担心服务器或底层运维设施,可以更专注代码和业务本身,也可以使代码进一步解耦,增加其重用性。

云函数示例

云函数目录结构

在Serverless小程序工程的server/functions目录下创建云函数目录,其中index.js是云函数getImageList的入口文件。

└── server/
    └── functions
           └── getImageList
                   └── index.js

云函数代码结构

以下代码示例展示了如何从数据库images里面查出特定用户上传的图片记录。云函数里可以直接通过API调用数据存储,文件存储的服务资源以及其他云函数。

  • 当云函数被客户端或者其他云函数调用时,可以通过ctx.args获得调用传来的参数。
  • 可以通过ctx.logger方法打印不同类型的日志信息,然后在云函数控制台中查看执行日志。
  • 在云函数内通过ctx.env来获取环境参数,例如SpaceId、调用来源、客户端源IP和客户端UserAgent等信息。ctx.env是一个object,它包含MP_SPACE_ID(SpaceId),MP_SOURCE(调用来源),MP_USER_AGENT(客户端User-agent),MP_CLIENT_IP(客户端IP)。
  • 在云函数中,您可以直接调用同一环境(空间)的数据存储和文件存储服务以及获取当前请求用户的基本信息。ctx.mpserverless在云函数封装了小程序的基础服务, API使用方式和客户端一致。

     • 通过ctx.mpserverless.db调用云数据库能力,如ctx.mpserverless.db.collection('user').find({ uid: args.uid })。
     • **通过ctx.cloud调用支付宝/阿里云的各种开放接口能力,包括了支付宝的基础/会员/支付/安全/营销等开放接口,如创建小程序二维码,调用ctx.cloud.base.qrcode.create({urlParam:'pages/index/index', queryParam:'key=value', describe:'我是二维码'})**
     • 通过ctx.mpserverless.file调用文件存储能力,如ctx.mpserverless.**file**.deleteFile(**args**.filePathUrl)。
     • 通过ctx.mpserverless.user获取当前访问用户基本信息,如ctx.mpserverless.user.getInfo()。
     • 通过ctx.mpserverless.function调用云函数能力,如mpserverless.function.invoke('dataAnalytics', {range: 30})调用其他云函数。
     • 通过ctx.httpclient HTTP 请求方法,无需额外依赖,您就可以请求任何 HTTP 和 HTTPS 协议的 Web 服务。如ctx.httpclient.request(' https://www.alipay.com/x/notFound.htm' )。
    
module.exports = async (ctx) => {
  ctx.logger.info('%s %s', ctx.env.MP_SPACE_ID, ctx.args.username);
  const images = await ctx.mpserverless.db.collection('images').find({ owner: ctx.args.username });
  return { images };
};

云函数接收消息推送

支持通过云函数接收小程序消息推送(如支付状态变化触发云函数,应用授权消息触发云函数,应用审核/驳回消息触发云函数)等。

首先:设置云函数HTTP触发器路径

支付宝小程序云开发支持通过云函数接收小程序消息推送,如接收应用授权消息,应用审核以及驳回消息,支付状态变化消息。首先,我们需要在自己的云服务空间下新建并部署云函数用于处理对应的消息通知。云函数部署成功之后,我们需要开启云函数的HTTP触发器功能,并获取一个该云函数对应的HTTP触发路径,只要使用 HTTP请求就可以访问到云函数,同时该HTTP触发路径可以作为开放平台的应用网关以及支付接口的notify_url用作接收各类消息。开启云函数HTTP触发功能有两种途径

在阿里云OpenAPI Explorer控制台调用API开启

——在阿里云的API在线调试界面 https://help.aliyun.com/document_detail/158669.html 以及 https://help.aliyun.com/document_detail/153370.html 发起在线API调用。
——开启Space的HTTP触发功能调用接口 UpdateHttpTriggerConfig接口来开启Space的HTTP触发功能,注意需要设置EnableService为true。
系统会为开启HTTP触发功能的Space分配一个默认域名 (DefaultEndpoint) ,供HTTP触发使用。
——开启云函数的HTTP触发功能调用接口 UpdateFunction接口来为云函数设置HTTP触发路径
HttpTriggerPath ,只有设置了触发路径的云函数才能使用该功能。
——HTTP触发函数执行访问 https://${DefaultEndpoint}${HttpTriggerPath} http://${DefaultEndpoint}${HttpTriggerPath} ,即可触发对应的云函数执行。

通过支付宝小程序命令行工具alipaydev一键开启(该功能将于2020/10上线,敬请期待)
• 安装alipaydev命令行工具,进行初始化配置。参考 https://opendocs.alipay.com/mini/alipaydev 的安装以及工具初始化配置说明。
• 执行 alipaydev cloud function httptrigger 命令,执行成功后会在命令行界面返回完整的云函数HTTP触发路径,该路径既可以直接使用HTTP请求访问,也可以作为应用网关或notify_url接收支付消息变化推送。
需要注意的是,每次调用UpdateFunction接口都会使之前生成的云函数触发路径的默认域名
(DefaultEndpoint) 发生变化。

云函数接收应用授权消息

将云函数的HTTP触发路径设置为应用的应用网关。
image.png
在云函数里处理应用授权的通知消息,应用授权通知的消息格式详细见 授权通知消息参数说明。在云函数里,我们解析出应用授权通知里的参数,将授权的应用appId,应用授权令牌appAuthToken,商户userId等参数存储在云数据库。云函数示例代码如下:

module.exports = async function (ctx) {
    const { args, mpserverless } = ctx
    // 1.解析args里的授权通知参数
    const { body } = args;
    ctx.logger.info('<---authCallback body--->',body);
    let jsonObj = query2Json(body);
    ctx.logger.info('<---authCallback jsonObj--->',jsonObj);
    // 若 notify_type=open_app_auth_notify 且 status=execute_auth 表示开放平台应用授权发生了重新授权
    // execute_auth 执行授权 cancel_auth 取消授权 refresh_auth 刷新授权
    const { notify_type, status, notify_id, app_id, auth_app_id, biz_content } = jsonObj;
    ctx.logger.info('<---authCallback notify_id|notify_type|status --->',notify_id, notify_type, status);
    const bizContentObj = JSON.parse(biz_content);
    const { detail } = bizContentObj;
    const { app_auth_token, auth_time, user_id } = detail;
    ctx.logger.info('<---authCallback auth_app_id|user_id|app_auth_token|auth_time --->',auth_app_id, user_id, app_auth_token, auth_time);
    if(notify_type == 'open_app_auth_notify' && (status == 'execute_auth'||status=='refresh_auth')) {
        // 执行授权通知+刷新授权通知消息,存储(auth_app_id)(uk) app_auth_token user_id auth_time
        await mpserverless.db.collection('auth_config').replaceOne({
            auth_app_id: auth_app_id
        }, {
            auth_app_id, app_auth_token, user_id, auth_time, 
            // 执行授权或刷新,valid=true
            valid: true
        }, {
            upsert: true
        })
    } else if(notify_type == 'open_app_auth_notify' && status == 'cancel_auth') {
        // 取消授权通知消息
        await mpserverless.db.collection('auth_config').updateOne({
            auth_app_id: auth_app_id
        }, {
            $set: { 
                valid: false
            }
        })
    }
    return {
        stat: 'ok'
    }
  };
  
  function query2Json(str) {
    var obj = {}, pairs = str.split('&'), d = decodeURIComponent, name, value;
    pairs.forEach(element => {
        pair = element.split('=');
        name = d(pair[0]);
        value = d(pair[1]);
        obj[name] = value;
    });
    return obj;    
  }

云函数接收支付状态变化消息

**将云函数的HTTP触发路径作为支付创建云调用API的notify_url参数。
**
——在小程序端使用云调用客户端SDK发起支付创建

//app.js中初始化云调用SDK时,将云函数的HTTP触发路径作为参数传入进行初始化
import cloud from 'alipay-serverless-sdk';

cloud.init(my.serverless,{
  notify:{url:"https://e1b3d2d79-bf5b-455d-8198-b762f0a24450.bspapp.com/http/notifyForPay"}
});

//在小程序页面js代码里,调用支付创建接口API
const res = await cloud.payment.common.crerate({
    subject: '小程序Serverless支付测试',
    outTradeNo: "demo" + new Date().getTime(),
    totalAmount: '0.01',
    buyerId: '2088202286335281'
  });

——在云函数代码中调用支付创建云调用API

// 云函数中使用云调用无需引入其他依赖,只需要使用ctx.cloud调用
module.exports = async function (ctx) {
  const res = await ctx.cloud.payment.common.create({
    // 参数接收自云函数调用端传入的参数
    subject: ctx.args.subject,
    outTradeNo: ctx.args.outTradeNo,
    totalAmount: ctx.args.totalAmount,
    buyerId: ctx.args.buyerId
  }, {
    // 传入接收支付宝服务器交易通知的http/https路径,也可以是云函数的http触发路径
    notify: {
        url: 'https://e1b3d2d79-bf5b-455d-8198-b762f0a24450.bspapp.com/http/notifyForPay'
    }
  });
  return res;
};

云调用

云调用是基于小程序 Serverless 的云函数来使用支付宝小程序开放接口的能力,可以方便的让开发者在小程序中和云函数中直接调用支付宝的后端开放接口,不需要关注服务端的相关配置,极大的减少了接入的流程,进一步降低了支付宝小程序的开发门槛。

云调用开放能力说明

云调用提供了基础能力、营销能力、会员能力、支付能力、安全能力和资金能力以及通用调用能力的接口调用,只需要开通云调用,你就能在小程序端和云函数端快捷的调用各类接口。

基础能力

  • 用户授权

• 获取授权访问令牌 cloud.base.oauth.getToken
• 刷新授权访问令牌 cloud.base.oauth.refreshToken

// 在云函数中使用云调用,无需引入其他依赖,只需要使用ctx.cloud调用
module.exports = async function (ctx) {
  const res = await ctx.cloud.base.oauth.getToken({
    // code参数接收自云函数调用处传入的参数
    code: ctx.args.authCode
  });
  return res;
};
// 在小程序端使用云调用
import cloud from 'alipaytest-serverless-sdk'

const res = await cloud.base.oauth.getToken('yourauthcode');
  • 小程序二维码

• 创建小程序二维码 cloud.base.qrcode.create

// 在云函数中使用云调用,无需引入其他依赖,只需要使用ctx.cloud调用
module.exports = async function (ctx) {
  const res = await ctx.cloud.base.qrcode.create({
    urlParam: 'pages/index/index',
    describe: '我的二维码描述',
    queryParam: 'key=value'
  });
  return res;
};
// 在小程序端使用云调用
import cloud from 'alipaytest-serverless-sdk'

const res = await cloud.base.qrcode.create('pages/index/index','key=value','我的二维码描述');

营销能力

  • 小程序模板消息

• 发送模板消息 cloud.marketing.templateMessage.send

// 在云函数中使用云调用,无需引入其他依赖,只需要使用ctx.cloud调用
module.exports = async function (ctx) {
  const res = await ctx.cloud.marketing.templateMessage.send({
    // 参数接收自云函数调用端传入的参数
    toUserId: ctx.args.toUserId,
    formId: ctx.args.formId,
    page: ctx.args.page,
    data: ctx.args.data,
    userTemplateId: ctx.args.userTemplateId  });
  return res;
};
// 在小程序端使用云调用
import cloud from 'alipaytest-serverless-sdk'

const res = await cloud.marketing.templateMessage.send('2088xxxxx','2017010100000000580012345678','MDI4YzIxMDE2M2I5YTQzYjUxNWE4MjA4NmU1MTIyYmM=','page/component/index','');

资金能力

  • 无密转账到支付宝账号

• 单笔转账 cloud.fund.transferAccount.transfer

// 在云函数中使用云调用,无需引入其他依赖,只需要使用ctx.cloud调用
module.exports = async function (ctx) {
  let payeeInfo = new Object({
    identity: this.data.payeeId,
    identity_type: 'ALIPAY_USER_ID'
  });
  const res = await ctx.cloud.fund.transferAccount.transfer({
    // 参数接收自云函数调用端传入的参数
    outBizNo: ctx.args.outBizNo,
    transAmount: ctx.args.transAmount,
    payee: payeeInfo,
    orderTitle: ctx.args.orderTitle
  });
  return res;
};
// 在小程序端使用云调用
import cloud from 'alipaytest-serverless-sdk'

const res = await cloud.fund.transferAccount.transfer('155983843433000','1.00',{
    identity: '2088xxxxxxxxx',
  identity_type: 'ALIPAY_USER_ID'
},'转账标题');

支付能力

  • 当面付

• 当面付交易付款 cloud.payment.faceToFace.pay

// 在云函数中使用云调用,无需引入其他依赖,只需要使用ctx.cloud调用
module.exports = async function (ctx) {
  const res = await ctx.cloud.payment.faceToFace.pay({
    // 参数接收自云函数调用端传入的参数
    subject: ctx.args.subject,
    outTradeNo: ctx.args.outTradeNo,
    totalAmount: ctx.args.totalAmount,
    authCode: ctx.args.authCode
  });
  return res;
};
// 在小程序端使用云调用
import cloud from 'alipaytest-serverless-sdk'

const res = await cloud.payment.faceToFace.pay('Iphone6 16G','20150320010101001','88.88','28763443825664394');

更多云调用支持的开放能力可以在 开放平台小程序云云调用专区 获得

相关实践学习
基于函数计算一键部署掌上游戏机
本场景介绍如何使用阿里云计算服务命令快速搭建一个掌上游戏机。
建立 Serverless 思维
本课程包括: Serverless 应用引擎的概念, 为开发者带来的实际价值, 以及让您了解常见的 Serverless 架构模式
目录
相关文章
|
20天前
|
存储 编解码 小程序
抖音小程序开发中遇见的坑点
在抖音小程序开发中,需注意10大坑点:遵守小程序限制与规范;解决兼容性问题;优化数据加载速度;适应分享功能限制;处理视频播放挑战;优化图片加载显示;管理资源文件;提升用户体验;考虑安全性;及时更新维护。通过测试、优化和遵循官方文档,可克服这些问题,打造优质小程序。
|
1月前
|
小程序 前端开发 API
小程序全栈开发中的多端适配与响应式布局
【4月更文挑战第12天】本文探讨了小程序全栈开发中的多端适配与响应式布局。多端适配涉及平台和设备适应,确保统一用户体验;响应式布局利用媒体查询和弹性布局维持不同设备的布局一致性。实践中,开发者可借助跨平台框架实现多平台开发,运用响应式布局技术适应不同设备。同时,注意兼容性、性能优化和用户体验,以提升小程序质量和用户体验。通过这些方法,开发者能更好地掌握小程序全栈开发。
|
1月前
|
小程序 前端开发 API
微信小程序全栈开发中的异常处理与日志记录
【4月更文挑战第12天】本文探讨了微信小程序全栈开发中的异常处理和日志记录,强调其对确保应用稳定性和用户体验的重要性。异常处理涵盖前端(网络、页面跳转、用户输入、逻辑异常)和后端(数据库、API、业务逻辑)方面;日志记录则关注关键操作和异常情况的追踪。实践中,前端可利用try-catch处理异常,后端借助日志框架记录异常,同时采用集中式日志管理工具提升分析效率。开发者应注意安全性、性能和团队协作,以优化异常处理与日志记录流程。
|
1月前
|
小程序 安全 数据安全/隐私保护
微信小程序全栈开发中的身份认证与授权机制
【4月更文挑战第12天】本文探讨了微信小程序全栈开发中的身份认证与授权机制。身份认证包括手机号验证、微信登录和第三方登录,而授权机制涉及角色权限控制、ACL和OAuth 2.0。实践中,开发者可利用微信登录获取用户信息,集成第三方登录,以及实施角色和ACL进行权限控制。注意点包括安全性、用户体验和合规性,以保障小程序的安全运行和良好体验。通过这些方法,开发者能有效掌握小程序全栈开发技术。
|
1月前
|
小程序 前端开发 安全
小程序全栈开发中的跨域问题及其解决方案
【4月更文挑战第12天】本文探讨了小程序全栈开发中的跨域问题及其解决方案。跨域问题源于浏览器安全策略,主要体现在前后端分离、第三方服务集成和数据共享上。为解决此问题,开发者可采用CORS、JSONP、代理服务器、数据交换格式和域名策略等方法。实践中需注意安全性、兼容性和性能。通过掌握这些解决方案,开发者能更好地处理小程序的跨域问题,提升用户体验。
|
1月前
|
小程序 前端开发 JavaScript
微信小程序全栈开发中的PWA技术应用
【4月更文挑战第12天】本文探讨了微信小程序全栈开发中PWA技术的应用,PWA结合Web的开放性和原生应用的性能,提供离线访问、后台运行、桌面图标和原生体验。开发者可利用Service Worker实现离线访问,Worker处理后台运行,Web App Manifest添加桌面图标,CSS和JavaScript提升原生体验。实践中需注意兼容性、性能优化和用户体验。PWA技术能提升小程序的性能和用户体验,助力开发者打造优质小程序。
|
2天前
|
小程序
开发小程序只要几百块?
开发小程序只要几百块?
13 0
|
2天前
|
Web App开发 数据采集 移动开发
开发uniapp过程中对app、微信小程序与h5的webview调试
开发uniapp过程中对app、微信小程序与h5的webview调试
|
13天前
|
小程序 前端开发 JavaScript
轻松学会微信小程序开发(一)
轻松学会微信小程序开发(一)
|
14天前
|
JSON 小程序 JavaScript
微信小程序开发1
微信小程序开发1

热门文章

最新文章