- Skyline 渲染引擎常见问题
Skyline 一定需要应用到整个小程序吗? 不需要,Skyline 支持按页面粒度开启,建议开发者逐个页面适配 在 Skyline 模式下,为什么使用真机调试会显示空白并且工具报错? 目前 Skyline 模式下暂不支持真机调试,建议使用真机预览完成调试,平台在尽快支持真机调试能力。 在 Skyline 模式下,为什么微信开发者工具热重载无响应? Skyline 模式暂不支持热重载,建议先关闭热重载,重新编译来预览渲染结果。后续平台将支持热重载能力。 开启 Skyline 后布局错乱 大多是由于没有全局滚动而导致挤压,以及 flex-direction 默认为 column 造成。前者只需要加上 scroll-view,后者可以在声明了display:flex 但又没指定 flex-direction的地方显示指定flex-direction:row。推荐开发者开启默认 Block 布局。 切换 Skyline后,为什么顶部原生导航栏消失? 不支持原生导航栏,需自行实现,或使用 weui 组件库 伪类及伪元素部分支持 对于伪类,目前只支持常用的 :first-child 和 :last-child 。其它伪类可通过按需添加 class 替代,如 :active 则手动给点击状态下的节点加个.active class 对于伪元素,目前只支持 ::before 和:after。其它伪元素建议用真实 WXML 节点实现。 全局固定元素失效 因不支持 fixed 导致,但由于没有全局滚动,在页面根节点下使用 absolute 即可达到 fixed 的效果,倘若封装原因无法移至页面根节点,可使用 root-portal 组件包裹 切换 Skyline 后,为什么 position: absolute 相对坐标不准确? 在 Skyline 模式下,所有节点默认是 relative,可能导致 absolute 相对坐标不准。建议开发者修改节点 position 或者修改相对坐标。 多段文本无法内联 因不支持 inline 布局导致,需改成 flex 布局实现,或者使用 text 组件包裹多段文本,而不是用 view 组件包裹,也可以使用 span 组件包裹 text 和 image 混合内联。如 、<span><image /></span>,<span><view style="width: 50px;"/></span> 多行文本的省略样式失效 在单行文本省略的基础上,通过 text 组件的 max-lines 属性设置最长行数,即 <text max-lines="{{2}}"></text> z-index 表现异常 这是由于 Skyline 不支持 web 标准的层叠上下文所致,只有在同层级的节点之前应用 z-index才有效,可根据实际情况调整取值 weui 扩展库无法使用 平台正在支持扩展库,预计近期上线。建议开发者使用 npm 安装 weui 组件库 后,将 node_ modules/weui-miniprogram 下的miniprogram_ dist 替换为 链接 中的 miniprogram_dist,然后在微信开发中工具中构建 npm 即可。 不支持组件 animate 动画接口 暂不支持组件 animate 动画接口。如需实现相关效果,可使用 worklet 动画机制 实现 svg 渲染不正确 Skyline 上的 SVG 不支持 <style> 选择器匹配,可自行转成内联的方式;不支持 rgba 格式,可使用 fill-opacity 替代;建议用 SVGO 在线工具优化 scroll-view 横向滚动不生效 横向滚动需打开 enable-flex 以兼容 WebView,同时 scroll-view 添加样式 display: flex; flex-direction: row;,scroll-view 子节点添加样式 flex-shrink: 0; icon-font 图标不显示 最新版本已支持伪元素,低版本可参考 代码片段 实现图标
2023-10-18 - 小程序备案指南(企业备案),持续更新
在mp后台: 1:未上架的小程 首页--小程序发布流程--小程序备案(查看能否备案)。 说明:此页面是未发布小程序前的首页页面,发布后的不一样,不要纠结找不找得到、没有这个页面。已经发布的看下方第二张图。 可以备案: [图片] 2:已上架的小程 可以备案: 小程序管理后台顶部会提示“小程序需补充备案信息”的提醒,点击【去备案】即可进入备案流程 或在设置--基本设置--小程序备案(去备案) 不能备案: 设置--基本设置--小程序备案(暂未对存量小程序开放) [图片] 企业小程序备案准备材料: 营业执照(副本扫描件或加盖公章的复印件,建议用副本扫描件,在上面加上**小程序备案所用,他用无效)。法人身份(最好是法人,负责人的也可以)证正反面照片,彩色的,拍照要拍全。管理员个人信息,姓名,身份证号,电话,备用电话,常用邮箱。(建议管理人员和负责人是同一个人)地址填写,最好是营业执照上地址,也可以是常用地址。前置审批/专项审批(具体可查看https://developers.weixin.qq.com/miniprogram/product/record_guidelines.html)。补充材料:根据规则提供包括但不限于授权书、党建证明、居住证、情况说明、承诺书等。互联网信息服务备案承诺书(单位)。资料提前准备好,需要法人扫码验证(和小程序认证差不多)。根据不同地区,准备资料可能有所差异,详细需要什么资料,审核备案时具体再做补充。如果上述没有看懂,转移这里,官方给出的流程https://developers.weixin.qq.com/miniprogram/product/record_guidelines.html[图片] 备案流程 [图片] 。。。。。。(持续更新详细步骤) 九月八号上午填写备案信息,九月十三号成功备案(本来九月八号当天发验证短信的,用户这边没及时验证,耽搁一天) [图片] 常见信息填写问题 1、备案流程中的主办单位、主体负责人具体指的是谁?主办单位 又称互联网信息服务主办者,主要指内容服务提供者,包括单位(如企业、政府机关等)和个人两类。主体负责人 个人:主体负责人应为主办单位本人。非个人:通常由单位法定代表人担任,如有特殊情况(如法代身份涉密、长期不在国内等)可授权单位高管担任。2、个体户没有公章怎么办?若个体工商户无公章,需要主体负责人手写日期+签名+盖手印+身份证号码,同时请在主体备注处备注“个体工商户无公章”。 3、填写小程序主体信息的通讯地址是指的什么地址?可填写主体证件上的地址,也可填写你实际的办公或住所地址。 若你是个人开发者:需精确到门牌号码,若已是最详细的地址或无门牌号的,在主体备注中说明“通信地址已为最详细”。若你是单位开发者需精确到门牌号码,且至少和主体证件所省份保持一致(如证件住所和通讯地址都是广东省),不能使用特殊符号(如:2#楼2-3-301);若已是最详细的地址,无门牌号的,在主体备注中说明“通信地址已为最详细”。备注:若你是北京地区,通讯地址填写时不能使用特殊符号(如:2#楼2-3-301)。4、什么情况下需要上传居住/暂住证明?当个人主体小程序备案申请人的身份证证件地址与申请小程序备案的省份不一致时,需要提供暂住证或居住证等证明材料。 涉及省份包括:吉林、上海、江苏、浙江、安徽、山东、湖北、广东、四川、贵州、云南。 5、小程序备案主体负责人必须填写法定代表人吗?每个省份管局的要求不一致,请按照备案小程序所属省管局要求进行填写,具体请参考: 类型地区主体负责人不是法定代表人需提供小程序主体负责人授权书吉林、山西、甘肃、江苏、安徽、四川 主体负责人必须是法定代表人:天津、内蒙古、陕西、宁夏、新疆、湖北、湖南、河南、上海、浙江、江西、贵州、重庆、云南、西藏、广西、广东、福建、黑龙江、河北、山东、青海 主体负责人可以不是法定代表人吉林、山西、甘肃、江苏、安徽、四川、海南、北京、辽宁 6、提示:主体负责人与法定代表人不一致,且备案所在地不支持法定代表人授权?你填写的【主体负责人】姓名与营业执照证件上的【法定代表人】姓名不一致,请重新填写,并保持一致。你在小程序备案 -【验证备案类型】页面中 - 主办人信息 - 选择地区中选择的省份,不支持法定代表人授权,【主体负责人】需填写【法定代表人】姓名。备案省份需填写小程序备案主体实际所在地,系统会根据你选择的区域自动匹配当地管局规则。7、在填写负责人手机号、应急手机号、邮箱时,提示:不允许被多人使用?在填写负责人手机号、应急手机号、邮箱时,提示“不允许被多人使用”,一般是出现了个人信息混用的情况,即手机号/应急手机号/邮箱填写的是其他人的信息。 在平台备案系统中,人,手机号,应急手机号,邮箱均一一绑定,同一个人允许为多个小程序备案(同一主体下),可以提交一致的手机号、应急手机号及邮箱,但不能出现不同人共用手机号/邮箱的情况。 小程序负责人授权书、小程序主体负责人授权、互联网信息服务承诺书怎么填写?小程序备案材料示例及填写指引:小程序备案材料示例小程序信息填写相关1、什么是服务内容标识?怎么选?服务内容标识是通信管局对各个行业的分类,平台部分行业类目与管局行业类目名称不完全不一致,建议根据备案小程序实际运营内容尽可能选择对应的服务内容标识。 若你是个人主体,请勿选择经营性质、企业/单位性质、涉及有关主管部门审批等的内容,如不可选择“批发和零售业-零售批发”。若你是单位主体,应选择与主体经营范围、资质相符合的内容,如你是医药公司,可选择“医疗服务-医药”,并上传《互联网药品信息服务许可证》。非政府单位不得选择“政务民生”内容。2、小程序负责人具体是指谁?是小程序管理员吗?个人主体:小程序负责人应为主办人本人。 非个人主体:小程序负责人应为本单位/公司具体负责小程序管理、小程序维护的相关人员。 3、怎么判断备案小程序是否要选择前置审批项?可参考:前置审批类别及审批部门 4、小程序管理员信息填写时,负责人姓名已填写为小程序管理员的姓名,为什么还是提示:负责人与小程序管理员不一致?出现这种提示一般都是第三方服务商协助创建的小程序未完善管理员实名信息,需补充管理员实名信息后才能进行备案,补充指引参考: 小程序MP后台-成员管理-管理员-修改。验证原管理员-填写原管理员身份证信息-扫码验证。绑定新管理员-填写【原管理员的信息】并提交,即完成管理员实名信息补充。相关文档可参考:如何完善小程序实名信息 小程序备案常见问题:https://developers.weixin.qq.com/community/develop/article/doc/000ac251a9c340df3e6073ee566c13 最后祝大家,一次备案成功
2023-10-08 - 小程序·云开发之数据库自动备份丨云开发101
小程序云开发之数据库自动备份 小程序云开发提供了方便的云数据库供我们直接使用,云开发使用了腾讯云提供的云数据库,拥有完善的数据保障机制,无需担心数据丢失。但是,我们还是不可避免的会担心数据库中数据的安全,比如不小心删除了数据集合,写入了脏数据等。 还好,云开发控制台提供了数据集合的导出,导入功能,我们可以手动备份数据库。不过,总是手动备份数据库也太麻烦了点,所有重复的事情都应该让代码去解决,下面我们就说说怎么搞定云开发数据库自动备份。 通过查阅微信的文档,可以发现云开发提供了数据导出接口databaseMigrateExport [代码]POST https://api.weixin.qq.com/tcb/databasemigrateexport?access_token=ACCESS_TOKEN [代码] 通过这个接口,结合云函数的定时触发功能,我们就可以做数据库定时自动备份了。梳理一下大致的流程: 创建一个定时触发的云函数 云函数调用接口,导出数据库备份文件 将备份文件上传到云存储中以供使用 1. 获取 access_token 调用微信的接口需要 access_token,所以我们首先要获取 access_token。通过文档了解到使用 auth.getAccessToken 接口可以用小程序的 appid 和 secret 获取 access_token。 [代码]// 获取 access_token request.get( `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appid}&secret=${secret}`, (err, res, body) => { if (err) { // 处理错误 return; } const data = JSON.parse(body); // data.access_token } ); [代码] 2. 创建数据库导出任务 获取 access_token 后,就可以使用 [代码]databaseMigrateExport[代码] 接口导出数据进行备份。 [代码]databaseMigrateExport[代码] 接口会创建一个数据库导出任务,并返回一个 job_id,这个 job_id 怎么用我们下面再说。显然数据库的数据导出并不是同步的,而是需要一定时间的,数据量越大导出所要花费的时间就越多,个人实测,2W 条记录,2M 大小,导出大概需要 3~5 S。 调用 [代码]databaseMigrateExport[代码] 接口需要传入环境 Id,存储文件路径,导出文件类型(1 为 JSON,2 为 CSV),以及一个 query 查询语句。 因为我们是做数据库备份,所以这里就导出 JSON 类型的数据,兼容性更好。需要备份的数据可以用 query 来约束,这里还是很灵活的,既可以是整个集合的数据,也可以是指定的部分数据,这里我们就使用 [代码]db.collection('data').get()[代码] 备份 data 集合的全部数据。同时我们使用当前时间作为文件名,方便以后使用时查找。 [代码]request.post( `https://api.weixin.qq.com/tcb/databasemigrateexport?access_token=${accessToken}`, { body: JSON.stringify({ env, file_path: `${date}.json`, file_type: '1', query: 'db.collection("data").get()' }) }, (err, res, body) => { if (err) { // 处理错误 return; } const data = JSON.parse(body); // data.job_id } ); [代码] 3. 查询任务状态,获取文件地址 在创建号数据库导出任务后,我们会得到一个 job_id,如果导出集合比较大,就会花费较长时间,这时我们可以使用 databaseMigrateQueryInfo 接口查询数据库导出的进度。 当导出完成后,会返回一个 [代码]file_url[代码],即可以下载数据库导出文件的临时链接。 [代码]request.post( `https://api.weixin.qq.com/tcb/databasemigratequeryinfo?access_token=${accessToken}`, { body: JSON.stringify({ env, job_id: jobId }) }, (err, res, body) => { if (err) { reject(err); } const data = JSON.parse(body); // data.file_url } ); [代码] 获取到文件下载链接之后,我们可以将文件下载下来,存入到自己的云存储中,做备份使用。如果不需要长时间的保留备份,就可以不用下载文件,只需要将 job_id 存储起来,当需要恢复备份的时候,通过 job_id 查询到新的链接,下载数据恢复即可。 至于 job_id 存在哪,就看个人想法了,这里就选择存放在数据库里。 [代码]await db.collection('db_back_info').add({ data: { date: new Date(), jobId: job_id } }); [代码] 4. 函数定时触发器 云函数支持定时触发器,可以按照设定的时间自动执行。云开发的定时触发器采用的 [代码]Cron[代码] 表达式语法,最大精度可以做的秒级,详细的使用方法可以参考官方文档:定时触发器 | 微信开放文档 这里我们配置函数每天凌晨 2 点触发,这样就可以每天都对数据库进行备份。在云函数目录下新建 [代码]config.json[代码]文件,写入如下内容: [代码]{ "triggers": [ { "name": "dbTrigger", "type": "timer", "config": "0 0 2 * * * *" } ] } [代码] 完整代码 最后,贴出可以在云函数中使用的完整代码,只需要创建一个定时触发的云函数,并设置好相关的环境变量即可使用 appid secret backupColl:需要备份的集合名称,如 ‘data’ backupInfoColl:存储备份信息的集合名称,如 ‘db_back_info’ 注意,云函数的默认超时时间是 3 秒,创建备份函数时,建议将超时时间设定到最大值 20S,留有足够的时间查询任务结果。 [代码]/* eslint-disable */ const request = require('request'); const cloud = require('wx-server-sdk'); // 环境变量 const env = 'xxxx'; cloud.init({ env }); // 换取 access_token async function getAccessToken(appid, secret) { return new Promise((resolve, reject) => { request.get( `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appid}&secret=${secret}`, (err, res, body) => { if (err) { reject(err); return; } resolve(JSON.parse(body)); } ); }); } // 创建导出任务 async function createExportJob(accessToken, collection) { const date = new Date().toISOString(); return new Promise((resolve, reject) => { request.post( `https://api.weixin.qq.com/tcb/databasemigrateexport?access_token=${accessToken}`, { body: JSON.stringify({ env, file_path: `${date}.json`, file_type: '1', query: `db.collection("${collection}").get()` }) }, (err, res, body) => { if (err) { reject(err); } resolve(JSON.parse(body)); } ); }); } // 查询导出任务状态 async function waitJobFinished(accessToken, jobId) { return new Promise((resolve, reject) => { // 轮训任务状态 const timer = setInterval(() => { request.post( `https://api.weixin.qq.com/tcb/databasemigratequeryinfo?access_token=${accessToken}`, { body: JSON.stringify({ env, job_id: jobId }) }, (err, res, body) => { if (err) { reject(err); } const { status, file_url } = JSON.parse(body); console.log('查询'); if (status === 'success') { clearInterval(timer); resolve(file_url); } } ); }, 500); }); } exports.main = async (event, context) => { // 从云函数环境变量中读取 appid 和 secret 以及数据集合 const { appid, secret, backupColl, backupInfoColl } = process.env; const db = cloud.database(); try { // 获取 access_token const { errmsg, access_token } = await getAccessToken(appid, secret); if (errmsg && errcode !== 0) { throw new Error(`获取 access_token 失败:${errmsg}` || '获取 access_token 为空'); } // 导出数据库 const { errmsg: jobErrMsg, errcode: jobErrCode, job_id } = await createExportJob(access_token, backupColl); // 打印到日志中 console.log(job_id); if (jobErrCode !== 0) { throw new Error(`创建数据库备份任务失败:${jobErrMsg}`); } // 将任务数据存入数据库 const res = await db.collection('db_back_info').add({ data: { date: new Date(), jobId: job_id } }); // 等待任务完成 const fileUrl = await waitJobFinished(access_token, job_id); console.log('导出成功', fileUrl); // 存储到数据库 await db .collection(backupInfoColl) .doc(res._id) .update({ data: { fileUrl } }); } catch (e) { throw new Error(`导出数据库异常:${e.message}`); } }; [代码] 如果你有关于使用云开发CloudBase相关的技术故事/技术实战经验想要跟大家分享,欢迎留言联系我们哦~比心! [图片]
2019-10-12 - 命令行工具出错?
cli login - initialize × #initialize-error: TypeError [ERR_INVALID_ARG_TYPE]: The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView. Received type number (3799)
2020-05-12 - 【云开发·云函数】分层(layer)实现代码复用,云函数之间共用底层文件
导读 当我们有很多云函数时,其中可能很多 [代码]中间件[代码] 、 [代码]工具[代码] 是共用的。 把这些 [代码]中间件[代码] 、 [代码]工具[代码] 复制到每个云函数下,是一件很麻烦的事情,而且如果发生了更新,还要重新复制。最重要的是,这种方式,不符合科学的设计模式。 云函数里的 层(layer) 就可以很好的解决我们这个问题。它是把我们共通需要的 [代码]中间件[代码] 、 [代码]工具[代码] 等文件放在一个公共的路径下,使用过程中只需要引用进来即可。 注意: 层暂时还没出现在小程序官方文档,但是可以在 [代码]腾讯云 - 云函数[代码]找到文档。 实操 这里我们使用 [代码]Nodejs8.9[代码] 来做示范 1. 先确认小程序已经开通了云开发 2. 登录腾讯云 打开登录界面 选择【其他登录方式 - 微信公众号 - 扫码选择对应的小程序(不是公众号)】. [图片] 注意:小程序云开发和腾讯云的账户体系其实是有关联的,可以把腾讯云面板看作更高级的云开发面板 3. 编写层代码 编写以下代码,并保存为 [代码]demo.js[代码] [代码]exports.main = async (event) => { return "hello,layer." } [代码] 把 [代码]demo.js[代码] 打包成 [代码]demo.zip压缩包[代码] 4. 创建分层 打开云函数面板. 点击左侧菜单的『层』 地域选择『上海』 点击『新建按钮』 层名称:demo 提交方法:本地上传zip包 层代码:选择上一步打包的 [代码]demo.zip[代码] 压缩包 运行环境:Nodejs8.9 [图片] 点击提交 注意: 有些压缩软件压缩后,会多一层文件夹,需要注意下,压缩包内打开应该直接就是文件 [代码]demo.js[代码] 没有多一层文件夹。 5. 小程序·云开发面板创建云函数 创建云函数 [图片] 修改 [代码]云函数 demo 下的 index.js[代码] 代码并上传 [代码]var hello = require("demo.js") exports.main = (event, context, callback) => { return hello.main() }; [代码] 6. 云函数绑定层 回到 腾讯云 云函数面板,选择左侧菜单 [代码]函数服务[代码] 注意左上角的 命名空间 选择小程序云开发的命名空间,地域:上海 选择刚创建的 [代码]demo[代码] 云函数 点击 [代码]层管理[代码] 绑定刚创建的 [代码]demo[代码] 层 7. 调试 还是 [代码]demo[代码] 的云函数里,点击 [代码]函数代码[代码] 项 点击测试,返回结果 [代码]"hello,layer."[代码] 既成功 [图片] Q&A 问:为什么云函数里可以直接[代码]require("demo.js")[代码] 引入 [代码]demo.js[代码] ? 答:绑定层后,会根据顺序把层文件放在系统目录 [代码]/opt[代码] 下,然后该目录在 Node.js 环境下又在环境变量里。当引入 [代码]demo.js[代码] 在当前目录找不到时,会尝试在环境变量内查找。所以云函数可以找到该文件。 再问:如果层的文件名和云函数列表的文件名冲突,岂不是会引入错误? 答:是的,这时候可以使用绝对路径确保引入的是层文件 [代码]require("/opt/demo.js")[代码] 再再问:如果云函数绑定了多个层,每个层里都有 [代码]demo.js[代码] 会怎么样? 答:会根据层的顺序,逐个覆盖文件,最终 [代码]/opt/demo.js[代码] 文件是最后一层的文件。 再再再问:环境变量除了这个路径,还有哪些路径? 答:这里有一份各语言的环境变量路径,可以参考下,具体查看文档 关环境变量 路径 THONPATH [代码]/var/user:/opt[代码] ASSPATH [代码]/var/runtime/java8:/var/runtime/java8/lib/*:/opt[代码] DE_PATH [代码]/var/user:/var/user/node_modules:/var/lang/node6/lib/node_modules:/opt:/opt/node_modules[代码] 问:云函数只支持 [代码]Nodejs8.9[代码] 版本吗? 答:在小程序云开发面板里,确实只能创建。但是可以通过服务端 SDK 创建以下语言支持。 Python 3.6 Python 2.7 Nodejs 10.15 Nodejs 8.9 Nodejs 6.10 Php 7.2 Php 5.6 Java 8 Golang 1 持续更新… 参考资料 腾讯云·云函数文档
2020-05-26 - [拎包哥] 批量下载云开发云存储的文件到pc端
官方教程 注:第2步和第3部的代码是反过来的。 [图片] 我的步骤: 0.按照官方教程安装tcb脚手架。 1.在桌面新建文件夹hellowWorld,新建cloudbaserc.json,json里的内容为: [图片] { "envId":"你的云开发环境的id" } 2.在cmd输入命令行。 e.g. 下载云存储里的qrCode文件夹到PC端文件夹(桌面的helloWorld文件夹)。 注:--dir在这里的意思是声明前面的 . 是一个文件夹,不需要另外修改。 [图片] tcb storage download qrCode . --dir
2021-09-28 - 「笔记」简单实现服务端动态控制原生小程序界面灰色模式开关
前言 在遇到公祭日或其它特殊日子的时候,我们需要将我们的网站、小程序变成灰色(黑白)模式,如果是在网页端比较简单,只需设置*、html最外层标签的样式设置filter: grayscale(100%)即可。但是在小程序中如果直接设置page的样式的话会导致小程序内使用flex失效,布局出现错位的情况。 如何解决错位问题?以及如何通过服务端动态控制灰色模式开关请看下文。 注:此方式无法控制非自定义导航栏颜色,如想要实现更完美的效果,请配合使用自定义导航栏。 原生小程序前端设置灰色模式: wxml <view class=“grayscale”> <view class=“content”></view> …小程序代码 </view> wxss .grayscale .content, .grayscale text, .grayscale button { -moz-filter: grayscale(100%); -ms-filter: grayscale(100%); -o-filter: grayscale(100%); filter: grayscale(100%); } 第三方UI组件/库(如:vant) .grayscale .van-goods-action, .grayscale .van-submit-bar, .grayscale .van-swipe-cell { -moz-filter: grayscale(100%); -ms-filter: grayscale(100%); -o-filter: grayscale(100%); filter: grayscale(100%); } 切忌直接设置 page { filter: grayscale(100%); } 小结:简单来说,就是把样式控制明确到具体的标签。 服务端动态控制 接下来讲我们利用小程序的数据预拉取来实现动态开关。 之所以选择使用数据预拉取来控制,是因为灰色模式并不是我们日常运营所需,如果单独封装到一个请求中去,会造成不必要的资源浪费,而且数据预拉取会在用户每次访问小程序的时候都会执行一次,所以能够保证尽可能实时获取到最新的状态,但是因为本身也是异步请求,所以无法100%保证页面加载完之前,就能够实时响应,所以返回的class并没有直接设置在全局变量globalData中,而是先存到本地存储Storage里,当我们在小程序后台关闭数据预拉取后,小程序端便不会再去请求相关接口,这样就做到了随时控制开关的效果了。 实现方式: app.js App({ onLaunch: async function (options) { // 此处用于服务端鉴权,可根据自身情况设置 wx.setBackgroundFetchToken({ token: ‘grayscale’ }) wx.onBackgroundFetchData((res) => { if(res.fetchedData && res.fetchedData.class) { wx.setStorageSync(‘class’, res.fetchedData.class); } }) }, globalData: { grayscale: wx.getStorageSync(“class”).grayscale || “” } }) 需要灰色模式的wxml <view class="{{grayscale}}"> <view class=“content”></view> …小程序代码 </view> 需要灰色模式的js const app = getApp() Page({ data: { grayscale: app.globalData.class.grayscale } }) 服务端(node.js)接收到微信推送的get请求后返回数据 ctx.body = { class: { grayscale: “grayscale” } } PS:以上方案仅供参考,当前方案在微信开发者工具中因缓存问题无法实时控制,iOS端基本上是没什么大问题,如果其它更好的方案可自行处理。
2022-12-03 - 「笔记」字节跳动小程序如何接入腾讯云CloudBase?
前言 最近在把微信小程序迁移至字节跳动小程序,由于服务端使用了腾讯云 CloudBase,网上搜索了一遍,文章千篇一律,都是复制腾讯云官方1年以前的适配器文档,在经过和腾讯云官方技术人员沟通后终于成功解决问题。 安装 npm i @cloudbase/js-sdk -S npm i @maoyan/cloudbase-adapter-tt_mp -S 使用 由于字节跳动小程序没有提供getAccountInfoSync()接口,无法通过接口获取appId 所以需要将appId设置到字节跳动小程序app对象上。 [代码]App({ onLaunch(options) { this.appId = appId } }) [代码] 腾讯云 CloudBase 安全配置 由于字节跳动小程序使用云开发不享受微信生态下的免鉴权,要在终端应用(如APP、小程序等)中使用云开发的身份验证服务,需要将授权的应用加入白名单,并在SDK使用时传入分配的凭证信息。 腾讯云 CloudBase 登陆授权 为了增加安全性,建议开启匿名登陆。启动匿名登录后,用户将不需要登录即可访问应用。如果有更严格的安全要求,可以自行开启其它身份验证方式。 完整代码 [代码]import tcb from '@cloudbase/js-sdk'; import { adapter } from '@maoyan/cloudbase-adapter-tt_mp'; let app; App({ onLaunch(options) { // appId必须设置 this.appId = "字节跳动小程序的appid"; tcb.useAdapters(adapter); // 腾讯云共享环境初始化 app = tcb.init({ env: '云环境id', appSign: '应用标识', // 需要设置成字节跳动小程序的appid appSecret: { appAccessKeyId: '版本', appAccessKey: '凭证' } }) // 匿名登陆 const auth = app.auth() const loginState = auth.anonymousAuthProvider().signIn() let data = await app.callFunction({ name: "云函数名", data: "参数" }); console.log(data) } }) [代码]
2022-03-03 - 浅析小程序云开发数据库核心能力及最佳实践
作者:王国洗、邓坤力 随着用户量的不断增多,用户需求的不断变多,云开发的迭代速度也越来越快,云开发推出了不少的新功能,这篇文章,将历数这些云开发的新功能,看看你都用上了没。 云开发数据库基础能力概览 云开发数据库主要提供的是一个 JSON 文档型数据库, JSON 数据格式让他对于前端开发十分的油耗,开发者可以轻松的完成数据的修改。此外,在数据库基础之上,云开发还提供了丰富的数据类型和多个平台的 SDK,让开发者可以在各个平台完成自己的业务开发。不仅如此,云开发数据库还提供数据库的安全规则控制,让开发者得以实现更加细粒度的权限控制。对云开发概念不熟悉的同学可以查看产品文档。 [图片] 当然,除了上面提到的这些基础能力以外,还有很多其他的特色能力,可以帮助你更好的完成自己的业务开发。接下来,我们来看看这些特色能力。 自定义告警 为了辅助业务监控服务质量,云开发为数据库提供了自定义告警能力,开发者可以借助监控能力,来实现监控服务的可用性。 对于开发者来说,可以借助云开发提供的自定义告警能力,来完成业务质量的监控、问题的快速触达,将问题扼杀在摇篮之中。 [图片] 权限管理 脱离了安全,业务就没有任何保证可言。在数据库权限设置方面,云开发提供了两种设置,第一种是初期提供的基础的四种简易权限设置,第二种是灵活的、可自定义的权限控制,即数据库安全规则。每个集合可以拥有一种权限配置,权限配置的规则是作用在集合的每个记录上的。 通过不同粒度的权限控制方式,开发者可以十分简单的实现各种不同权限控制能力。不仅如此,因为有了权限控制能力,云开发的数据库可以在前端直接操作,可以有效的提升研发效率。 [图片] 导入导出管理 针对不同的业务,云开发提供了数据导入、数据导出、数据回档功能。 针对有需求从传统业务迁移至云开发上的开发者,可以选用云开发提供的数据导入能力,通过将数据转换成 JSON 或 CSV 格式,来导入到云开发数据库中。类似的,如果业务需要对数据进行离线统计分析的时候,就可以借助数据导出的功能,实现本地的数据分析。 除此之外,从安全的角度考虑,我们面向开发者开放了数据回档的功能,简单的几下点击,就可以实现数据的快速回档,告别删库跑路。 [图片] 索引管理 数据库索引可以提升数据库查询的性能,云开发也提供了相应的索引管理功能,帮助开发者方便快捷的完成索引的创建,优化数据库查询的性能。目前云开发数据库索引支持键值索引和地理位置索引,后续也有可能会支持 Hash 索引和全文索引等。 开发者可以借助云开发提供的索引功能,优化数据库查询的性能,提升产品的体验。 [图片] 如何创建高效的数据库索引 最佳实践1:每个生产环境查询都应有索引支持 首先我们需要记得,每一个我们放到线上生产环境的查询,都应该配有索引支持,只有有索引支持才能尽可能规避数据量和请求量上涨带来的慢查询风险。 最佳实践 2:尽可能使用组合索引 如果我们的查询条件包含多个字段,那么为这些字段创建一个组合索引后的查询效率是比只使用单字段索引要高很多的。像下图这个case [图片] 最佳实践 3:组合索引字段顺序策略 要注意组合索引中字段的顺序。比如下图这样一个包含两个查询字段,一个排序字段的这么一个查询语句,那我们在创建组合索引的时候是不是任意顺序都可以呢?确认任意顺序都能让这个查询语句用到索引,但那不一定是最优的顺序。最优的顺序是b,c,a,为什么呢?在创建组合索引时,我们应遵循这么一个字段顺序原则:等于>排序>范围查询字段 [图片] 最佳实践4:注意组合索引升降 要注意组合索引的升降序,这个升降序也并不是可以随意指定的,特定的升降序组合只可以满足特定的排序查询。以下面这个查询为例。 [图片] 最佳实践 5:利用覆盖索引高效查询 可以利用好覆盖索引。什么是覆盖查询,就是当查询条件和查询要返回的所有字段都在索引中的时候,就是覆盖查询,当命中覆盖查询的时候,查询不再需要去读取数据,直接从索引中取得结果,可以进一步更加的高效。下面这个查询是一个例子: [图片] 最佳实践 6:数组查询也要建索引 要记住数组也可以使用索引,像下图中的示例,a 字段是个数字数组,b字段是个对象嵌套数组,它们其实都可以利用到索引,像a字段我们可以直接建个索引,如果需要查b数组里面的x字段,那可以建个b.x的字段索引。 [图片] 最佳实践 7:去除多余索引 要去除多余的索引。什么是多余的索引呢?首先当然是没用到的索引,过时的索引,这些都可以去掉,但还有一类多余的索引需要特别提及,那就是重复前缀的索引和相反升降序的索引,这些也是多余的索引。 [图片] 最佳实践 8:大数据量下避免使用低区分度操作符 在大数据量下避免使用低区分度的操作符,这些都是取反的操作符,他们的区分度通常都很低,因此很难高效的使用索引,因此只应该在少量的时候使用。 希望以上的能力介绍和最佳实践建议,可以帮助到大家更好地使用到云开发数据库。如果你对上面8个最佳实践建议还无法很好地理解,这也没有关系,因为微信开发者工具很快就会推出一个自动分析数据库查询语句,然后自动给出索引建议的能力,这项能力可以让大家在偏离数据库索引最佳实践的时候给出提示和警告,从而让小程序的数据库查询都尽可能有正确、完整的索引保障,并且还是遵循最佳实践的方式建立的索引。 本分享课程视频可以在这里查看:https://cloud.tencent.com/developer/salon/live-1234 【相关指引】 云开发(CloudBase)是云端一体化的后端云服务,采用 serverless 架构,免去了移动应用构建中繁琐的服务器搭建和运维。同时云开发提供的静态托管、命令行工具(CLI)、Flutter SDK 等能力极大的降低了应用开发的门槛。使用云开发可以快速构建完整的小程序/小游戏、H5、Web、移动 App 等应用。 产品文档:https://cloud.tencent.com/product/tcb 技术文档:https://cloudbase.net 技术交流加Q群:601134960 最新资讯关注微信公众号【腾讯云云开发】 [图片]
2020-07-06 - 关闭微信小程序直播组件,直播中的分享和复制链接
1、取消复制链接和分享,微信小程序里面可以直接用,但是这个代码必须在发布后,(复制链接)才能看到被屏蔽的效果,开发版不行,这个也是测试后才发现的,没人提到这一块。走了一些弯路 onLoad: function() { wx.hideShareMenu(); }, 正式版效果图 [图片] 2、小程序的直播组件,在创建直播的时候,设置 【关闭分享】。这样直播过程中,就可以实现上面的功能。禁止分享和复制链接 备注。留给需要的人。
2021-07-08 - 一个小程序最多同时开多少个直播间?小程序直播组件直播间的直播时长是否有限制?
同一个小程序最多可以支持50个直播间同时直播,每天的直播上限也是50场。每个直播间不能直播超过12小时。
2020-04-17 - (16)小游戏渲染
《跳一跳》小游戏在 2017年12月28日正式发布,一周内 DAU 突破一亿,为小游戏开放生态赢得口碑。它操作简单,节奏轻快,凭借着快速复活机制以及强大的社交属性掀起了一股全民潮流。 其实,这个小游戏里仅有两个元素,黑色小人和各色基座。游戏规则也很简单,起跳前,小黑人压缩自己的身体来蓄力,根据蓄力时间决定距离来跳到下一个基座上。 今天的小故事,想要跟大家分享小游戏的渲染能力,我们以跳一跳唱片机为例,简要介绍一下如何展现一个三维物体~ ( 3D渲染引擎选用 Three.js ) [图片] 步骤一 创建一个场景 Scene 游戏的容器,用来放置光源,照相机和唱片机。 let scene = new THREE.Scene() 步骤二 选择合适的照相机 Camera 抽象来说,照相机定义了三维空间到二维屏幕的投影方式。 因投影方式不同,相机又分为透视投影相机和正交投影相机。 透视投影中的四棱柱和正交投影中的立方体被称为视景体,它是三维世界里屏幕上可见的区域,也就是照相机的视野。 视景体外的物体会被剪裁掉不参与渲染。透视投影更接近真实世界,有近大远小的感觉。而正交投影将物体以原比例平行投影到近剪裁面上,不会有大小缩放。 在跳一跳中我们使用了正交投影相机。 [图片] let camera = new THREE.OrthographicCamera( width / - 2, width / 2, height / 2, height / - 2, near, far ) 步骤三 创建光源 light let ambientLight = new THREE.AmbientLight(0xffffff, 0.8); let directionalLight = new THREE.DirectionalLight(0xffffff, 0.28); 创建一个环境光和直射光, 环境光没有特定光源,它将光线均匀照射在场景中。直射光模拟真实世界太阳光。 步骤四 定义几何体 Geometry, 材质 Material,合成 Mesh Geometry 几何体,定义了一个物体的形状,包含顶点,线,面和法向量等信息。 let boxGeometry = new THREE.BoxGeometry(2, 2, 2) 对于唱片机我们创建了三个几何体,两个长方体和一个圆柱体。 [图片] Material 材质,定义了一个物体的外观,例如颜色,透明度,光照属性,融合模式。 顶部透明盖子,底座和唱片的使用的Lambert材质,这种材质只考虑漫反射而不考虑镜面反射, 通常用于创建较暗淡无高光的物体, 其中 texture 是纹理贴图,我们通过纹理映射将这个二维图像贴到三维的方块上。 let transparentMaterial = new THREE.MeshLambertMaterial({ color: ‘white’, transparent: true, opacity: 0.5, map: texture }) 最后我们通过 Mesh 我们将材质应用到几何体上。 let box = new THREE.Mesh(boxGeometry, transparentMaterial) 步骤五 使用渲染器 Renderer 渲染整个场景 最后我们将 box,camera 设置合适的位置后加入到场景中,再使用 Three.js 的渲染器 renderer 之后就可以看到音乐盒了~ renderer.render(scene, camera) 至此,我们完成了一个 3D 场景渲染到 2D 屏幕的渲染流水线中的应用程序阶段,这个阶段我们将渲染所需的几何信息(点,线,面,法线等信息)传递到渲染流水线的后续阶段。后续的小故事我们会介绍调用渲染器 render 方法后 GPU 是如何处理几何信息并最终渲染图像到屏幕上的。 QA&共性问题 Q 一般的 3D 游戏 HUD 层(平视显示器)采用 DOM 来显示,例如排行榜,交互按钮。或者使用另一个 canvas 叠在游戏 canvas 上。但是小游戏只支持一个可见 canvas,并且不支持 DOM。这种情况在小游戏里面,应该如何处理呢? A 可以封装 HUD 层并将其放在游戏 canvas 中,将整个HUD画在了一张离屏 canvas 中,然后将该 canvas 转化为纹理贴图,再将其贴在游戏的 3D 平面模型上。 后续的小故事会介绍如何将 HUD 分解为 3D 组件的形式来开发。
2018-08-17 - 云函数设置时区,对聚合操作dayOfYear无效
云函数设置时区无效, 8点前的数据在dayOfYear中还是归在昨天, 函数里设置 process.env.Tz ='Asia/Shanghai'也没用 什么原因?应该怎么处理 const db = cloud.database() const _ = db.command const $ = _.aggregate const coll_car = db.collection("car") coll_car.aggregate() .match(_.expr( $.and([ $.eq([$.month('$startDateTime'), month]), $.eq([$.year('$startDateTime'), year]), ]) )) .group({ _id: $.dayOfYear("$startDateTime"), num: $.sum(1) }) .end() .then(res => { console.log(res) }).catch(err => { console.log(err) })
2021-03-15 - 小程序云开发原生支持微信支付
各位 小程序·云开发 开发者: 小程序·云开发新推出原生微信支付能力支持,开发者在云开发控制台可直接绑定微信支付商户,在绑定完成后可在云开发中原生接入微信支付。 使用云开发来实现相应的支付功能后,开发者无需关心证书、签名、微信支付服务器端文档,使用简单,代码较少,只需要调用相应的函数即可。此外,因为云开发基于微信私有协议实现,官方通过服务商提供支付接口对接支持,不依赖第三方模块,免去泄漏证书、支付情况等其他敏感信息的风险。同时,云开发还支持云函数接收微信支付进行支付和退款的回调,安全高效。 云开发现已支持从下单到退款的全流程微信支付接口: 统一下单接口查询订单关闭订单下载对账单申请退款查询退款更多能力说明与接入方式请查看《云开发微信支付能力说明》、《API 文档》。 接入过程如有疑问或建议,欢迎在 #云开发 社区与我们一起交流。 微信团队 2020年05月15日
2020-06-17 - 新能力|云调用支持微信支付啦!
导语 小程序·云开发的云调用能力,让用户可以免鉴权快速调用微信的开放能力,极大节约了开发成本。现在,云调用已支持微信支付,用户在云开发控制台可直接绑定微信支付商户,在绑定完成后可在云开发中原生接入微信支付。 使用云开发的云调用来实现相应的支付功能后,开发者无需关心证书、签名、微信支付服务器端文档,使用简单,代码较少,只需要调用相应的函数即可。此外,因为云调用基于微信私有协议实现,官方通过服务商提供支付接口对接支持,不依赖第三方模块,免去泄漏证书、支付情况等其他敏感信息的风险。此外,云开发的云调用还支持云函数作为微信支付进行支付和退款的回调地址,不再需要定时轮询,更加高效。 云调用支付支持接口 云调用支付现已支持如下接口 统一下单接口 查询订单 关闭订单 下载对账单 申请退款 查询退款 如何接入 准备工作 微信开发者工具 Nightly 版 1.02.2005111 及更新的版本 需要已经开通了微信支付,且已绑定了商户号的小程序。 如何开通 在微信开发者工具中,使用绑定的微信小程序账号,打开云开发控制台,在云开发控制台中的 设置 - 全局设置 中添加商户号 [图片] 添加后,需要在绑定的商户号管理员在微信支付提供的【服务商助手】小程序上确认授权。 如果需要 jsapi 和 api 退款权限,需要前往微信支付商户平台我的授权产品中进行确认授权,完成授权后即可调用微信支付相关接口能力。 支付 Demo 代码 在云函数中,调用 cloudPay.unifiedOrder ,即可生成小程序侧调用支付接口所需请求结果 [代码]cloud.cloudPay.unifiedOrder({ "body" : "小秋TIT店-超市", "outTradeNo" : "${Date.now().toString().slice(3)}", "spbillCreateIp" : "127.0.0.1", "subMchId" : "1900009231", "subAppid" : "wxe5f52902cf4de896", "totalFee" : 1, "envId": "test-f0b102", "functionName": "pay_cb" }) [代码] 关键开发流程 小程序调用云函数,在云函数中调用统一下单接口,参数中带上接收异步支付结果的云函数名和其所在云环境 ID 统一下单接口返回的成功结果对象中有 payment 字段,该字段即是小程序端发起支付的接口(wx.requestPayment)所需的所有信息 小程序端拿到云函数结果,调用 wx.requestPayemnt 发起支付 支付完成后,在统一下单接口中配置的云函数将收到支付结果通知 支付回调 微信支付云调用在调用时,需要传递 envId 和 functionName 这两个参数,这两个参数将会在微信支付成功后,发送相应的消息通知,来告知开发者用户的支付状态。 相关文档 云调用微信支付能力说明:https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/wechatpay.html API 文档:https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-sdk-api/open/pay/Cloud.CloudPay.html 视频教程 为了帮助你掌握云调用微信支付,这里为你准备了快速上手视频~快去试试吧~ https://www.bilibili.com/video/BV1Tz4y1d7CX 总结 云开发的微信支付云调用能力,可以让更多的开发者安全、快捷的实现支付,让企业的资金更加的安全。 小调研 云调用现在已经支持了微信支付,除了微信支付,你还有什么特别想要的功能么?不妨在下方评论区中留言告诉我们。
2020-09-14 - 微信第三方开放平台中 平台型服务商 定制化开发服务商 有什么区别
这两个服务商有什么区别?如果我要开发一个小程序模板给商户使用,我应该选哪个
2019-03-12 - 云开发数据库,如何比较2个字段?
云开发数据库中有张表,表里有a、b 2个字段,现在要查询a>b的数据,该如何实现。
2020-05-12 - 虚拟业务指南请收好。
在小程序生态中,基于苹果运营规范,小程序内暂不支持iOS端虚拟支付业务。为此小编为大家整理了一份虚拟支付业务指南,希望大家在做虚拟业务时有所帮助: [视频] 那么,到底什么是虚拟支付业务呢? 虚拟支付业务是指购买非实物商品。比如:VIP会员、充值、录制课程、录制音频视频等虚拟产品。目前iOS端暂不支持虚拟支付业务。 我们常见iOS虚拟支付的不合规示例有哪些呢? 示例一 :小程序内存在付费购买虚拟内容或道具。商品多体现为提前编辑好的、录制好的虚拟商品。如录制视频课程、游戏道具。 整改建议 :建议去除小程序内所有付费购买虚拟服务,并根据提示修改相关内容及文案,文案可参照“由于相关规范,iOS功能暂不可用”。 [图片] 示例二 :付费解锁优质服务。多体现为提供虚拟商品的小程序可通过支付购买、开通虚拟会员等形式,体验小程序付费服务。比如:支付阅读章节小说、同城生活服务平台付费发帖/付费置顶等。 整改建议 :建议可以关闭iOS端虚拟支付通道,并将【马上充值】更改为【由于相关规范,iOS功能暂不可用】,并不再提供iOS端会员服务。 [图片] 示例三 :关闭iOS端虚拟支付功能后,虚拟商品页面仍然保留货架价格标签展示、购买/付费/订阅等功能或按钮。 整改建议 :建议去除小程序中的虚拟商品的价格展示,并更改为【免费】;并将【订阅 ¥128】更改为【由于相关规范,iOS功能暂不可用】,并不再提供iOS端虚拟商品购买服务。 [图片] 示例四 :关闭iOS端虚拟支付功能后,提供引导用户前往其他支付的路径/文案,完成虚拟支付闭环。 整 改建议 :建议去除iOS端小程序内引导用户前往其他支付路径/文案,并不再提供iOS端虚拟商品购买服务。 [图片] 示例五 :小程序含需要付费的虚拟商品,并设置限时免费的服务,限时免费结束后需付费才能继续提供服务。 整改建议 :建议将iOS端小程序中所有虚拟付费内容更改为免费,并不再提供iOS端虚拟商品购买服务。 [图片] 示例六 :关闭iOS端虚拟支付功能后,小程序中虚拟产品页面不可以含有付费性质的关键字(如:购买、已购、付费、支付等),包括但不限于功能按钮、功能页面、支付提示及任何商品介绍等。 整改建议 :建议将小程序iOS端虚拟产品页面中的文案/按钮/功能tab含有限制的关键字更改为【免费】或删除。并不再提供iOS端虚拟商品购买服务。 [图片] 如小程序内存在以上不合规的虚拟支付内容,请开发者重视并及时整改。对于首次违规的小程序,平台将下发站内信整改通知,并给予三天整改时间,请开发者按照提示在限期内完成整改。平台将会对到期未完成整改的小程序进行搜索策略调整,并在小程序功能使用上进行一定的限制,直到小程序完成内容整改。
2020-04-23 - 小程序示例
小程序官方示例Demo,包含云开发示例。
2020-06-17 - 微信支付APIv3的Nodejs版SDK,让开发变得简单不再繁琐
在向云端推送这个 [代码]wechatpay-axios-plugin[代码] 业务实现时,发现0.1系列还不够好用,还需要进行更多层级的包裹包装,遂再次做了重大更新,让SDK使用起来更简单、飘逸。 先看官方文档,每一个接口,文档都至少标示了[代码]请求URL[代码] [代码]请求方式[代码] [代码]请求参数[代码] [代码]返回参数[代码] 这几个要素,[代码]URL[代码] 可以拆分成 [代码]Base[代码] 及 [代码]URI[代码],按照这种思路,封装SDK其实完全就可以不用动脑,即,对[代码]URI[代码]资源的 [代码]POST[代码] 或 [代码]GET[代码] 请求(条件带上[代码]参数[代码]),取得[代码]返回参数[代码]。 更近一步,我们设想一下,如果把众多接口的[代码]URI[代码]按照斜线([代码]/[代码] [代码]slash[代码])分割,然后组织在一起,是不是就可以构建出一颗树,这颗树的每个节点(实体[代码]Entity[代码])都存在有若干个方法([代码]HTTP METHODs[代码]),这是不是就能把接口[代码]SDK实现[代码]更简单化了?! 例如: /v3/certificates /v3/bill/tradebill /v3/ecommerce/fund/withdraw /v3/ecommerce/profitsharing/orders /v3/marketing/busifavor/users/{openid}/coupons/{coupon_code}/appids/{appid} 树形化即: [代码]v3 ├── certificates ├── bill │ └── tradebill ├── ecommerce │ ├── fund │ │ └── withdraw │ └── profitsharing │ └── orders └── marketing └── busifavor └── users └── {openid} └── coupons └── {coupon_code} └── appids └── {appid} [代码] 按照这种树形构想,我们来看下需要做的[代码]封装实现[代码]工作: 把实体对象,按照实体的排列顺序,映射出请求的URI; 每个对象实体,包含有若干操作方法,其中可选带参数发起RPC请求; 随官方放出更多的接口,SDK需要能够弹性扩容; wechatpay-axios-plugin~0.2.0 版本实现了上述这3个目标,代码包如下截屏: [图片] 我们用伪代码来校验看一下这个[代码]封装实现[代码]: [代码]require('util').inspect.defaultOptions.depth = 10; const { Wechatpay } = require('wechatpay-axios-plugin'); const wxpay = new Wechatpay({mchid: '1', serial: '2', privateKey: '3', certs: {'4': '5'}}); wxpay.v3.certificates; wxpay.v3.bill.tradebill; wxpay.v3.ecommerce.fund.withdraw; wxpay.v3.marketing.busifavor.users['{openid}'].coupons.$coupon_code$.appids['wx233544546545989']; console.info(wxpay); //以下是输出内容 { entities: [], withEntities: [Function: withEntities], get: [AsyncFunction: get], post: [AsyncFunction: post], upload: [AsyncFunction: upload], v3: { entities: [ 'v3' ], withEntities: [Function: withEntities], get: [AsyncFunction: get], post: [AsyncFunction: post], upload: [AsyncFunction: upload], certificates: { entities: [ 'v3', 'certificates' ], withEntities: [Function: withEntities], get: [AsyncFunction: get], post: [AsyncFunction: post], upload: [AsyncFunction: upload] }, bill: { entities: [ 'v3', 'bill' ], withEntities: [Function: withEntities], get: [AsyncFunction: get], post: [AsyncFunction: post], upload: [AsyncFunction: upload], tradebill: { entities: [ 'v3', 'bill', 'tradebill' ], withEntities: [Function: withEntities], get: [AsyncFunction: get], post: [AsyncFunction: post], upload: [AsyncFunction: upload] } }, ecommerce: { entities: [ 'v3', 'ecommerce' ], withEntities: [Function: withEntities], get: [AsyncFunction: get], post: [AsyncFunction: post], upload: [AsyncFunction: upload], fund: { entities: [ 'v3', 'ecommerce', 'fund' ], withEntities: [Function: withEntities], get: [AsyncFunction: get], post: [AsyncFunction: post], upload: [AsyncFunction: upload], withdraw: { entities: [ 'v3', 'ecommerce', 'fund', 'withdraw' ], withEntities: [Function: withEntities], get: [AsyncFunction: get], post: [AsyncFunction: post], upload: [AsyncFunction: upload] } } }, marketing: { entities: [ 'v3', 'marketing' ], withEntities: [Function: withEntities], get: [AsyncFunction: get], post: [AsyncFunction: post], upload: [AsyncFunction: upload], busifavor: { entities: [ 'v3', 'marketing', 'busifavor' ], withEntities: [Function: withEntities], get: [AsyncFunction: get], post: [AsyncFunction: post], upload: [AsyncFunction: upload], users: { entities: [ 'v3', 'marketing', 'busifavor', 'users' ], withEntities: [Function: withEntities], get: [AsyncFunction: get], post: [AsyncFunction: post], upload: [AsyncFunction: upload], '{openid}': { entities: [ 'v3', 'marketing', 'busifavor', 'users', '{openid}' ], withEntities: [Function: withEntities], get: [AsyncFunction: get], post: [AsyncFunction: post], upload: [AsyncFunction: upload], coupons: { entities: [ 'v3', 'marketing', 'busifavor', 'users', '{openid}', 'coupons' ], withEntities: [Function: withEntities], get: [AsyncFunction: get], post: [AsyncFunction: post], upload: [AsyncFunction: upload], '$coupon_code$': { entities: [ 'v3', 'marketing', 'busifavor', 'users', '{openid}', 'coupons', '{coupon_code}' ], withEntities: [Function: withEntities], get: [AsyncFunction: get], post: [AsyncFunction: post], upload: [AsyncFunction: upload], appids: { entities: [ 'v3', 'marketing', 'busifavor', 'users', '{openid}', 'coupons', '{coupon_code}', 'appids' ], withEntities: [Function: withEntities], get: [AsyncFunction: get], post: [AsyncFunction: post], upload: [AsyncFunction: upload], wx233544546545989: { entities: [ 'v3', 'marketing', 'busifavor', 'users', '{openid}', 'coupons', '{coupon_code}', 'appids', 'wx233544546545989' ], withEntities: [Function: withEntities], get: [AsyncFunction: get], post: [AsyncFunction: post], upload: [AsyncFunction: upload] } } } } } } } } } } [代码] 注: API树实体节点,存储在每个 [代码]entities[代码] 属性上,方便后续的[代码]get[代码], [代码]post[代码] 抑或 [代码]upload[代码] 方法调用调用前,反构成最终请求的[代码]URI[代码];特别地,对于动态树实体节点来说,每个实体节点均提供了 [代码]withEntities[代码] 方法,用来在最终请求前,把动态实体节点替换成实际的值。 正常用法示例如下: [代码]const {Wechatpay} = require('wechatpay-axios-plugin'); const wxpay = new Wechatpay({/*初始化参数,README有*/}, {/*可选调整axios的参数*/}); //拿证书 wxpay.v3.certificates.get(); //带参申请交易账单 wxpay.v3.bill.tradebill.get({params: {bill_date}}); //带参发起账户余额提现 wxpay.v3.ecommerce.fund.withdraw.post({sub_mchid, out_request_no, amount, remark, bank_memo}); //查询用户单张券详情 wxpay.v3.marketing.busifavor.users['{openid}'].coupons.$coupon_code$.appids['wx233544546545989'].withEntities({openid, coupon_code}).get(); [代码] 请求APIv3是不是就“丧心病狂”般的简单了?! 详细功能说明及用法示例,npmjs及github的README均有。 如果喜欢,就给来个 赞 及 Star 吧。
2020-07-17 - 小程序云开发:可以一次性把所有云函数更新到服务器上吗?
请问各位开发大神,可以一次性把所有云函数更新到服务器上吗?现在要一个一个的点,很怕漏掉
2020-07-21 - 2019微信广告小程序流量主大会开放报名
7月25日,微信广告小程序流量主大会(WeChat Ads Flow 2019)将在上海举行。 2019年大会以“越简单,越丰富”为主题,我们将与大家分享微信广告如何通过更简单友好的商业化产品能力助力生态更加丰富繁荣,如何以更简单高效的流量变现工具帮助小程序小游戏开发者实现更丰富的价值回报。 微信小程序小游戏的发展趋势如何,微信广告为小程序小游戏开发者提供哪些升级的商业化解决方案,又有哪些新鲜有效的标杆流量主商业化案例?本次大会我们将为大家——解答。 参加大会,你将得到—— 微信广告官方团队现场解惑 重磅升级的小程序小游戏商业化解决方案 干货满满的标杆流量主经验分享 会程安排 上午 小程序流量主专场 从“简单”到“丰富”——小程序未来的变化与展望 全面剖析,助力小程序流量主高效变现—小程序流量主商业化解决方案分享 流量主说:工具类小程序的商业化变现实践——标杆工具类小程序流量主分享 流量主说:内容类小程序的商业化变现实践——标杆内容类小程序流量主分享 下午 小游戏流量主专场 立体洞察用户价值,简单实现商业变现——小游戏流量主商业化产品矩阵分享 多管齐下助力小游戏开发者获取价值回报——小游戏流量主商业化解决方案分享 优选为优质续航,合作让生态共赢——微信小游戏优选合作计划介绍 流量主说:如何做一款优质的小游戏——标杆小游戏流量主分享 时间地点 时间:2019年7月25日 小程序流量主专场10:00-12:00 小游戏流量主专场14:30-17:00 地点:上海普陀区安曼纳卓悦酒店 扫码或点击链接立即报名 [图片] https://tencentads.com/l/725xcxllzdhbmtms 温馨提醒 报名截止日期:2019年7月18日 报名信息提交后,我们将在20日24点前通过短信通知报名是否成功。请留意后续短信提醒。 欢迎来到微信广告小程序流量主大会,解锁微信小程序商业化全新攻略。期待与你一路同行,一同成长。
2019-07-12 - [视频教程]小程序新出的页面间通讯接口怎么用
[视频]
2019-07-13